(转)JAVA获得机器码的实现

标签: java 机器码 | 发表时间:2014-02-10 14:19 | 作者:
出处:http://jackyrong.iteye.com
http://yangshangchuan.iteye.com/blog/2012401

首先,定义了一个统一的接口,以支持不同操作系统不同实现的透明切换:

Java代码  收藏代码
/**
*生成机器码的接口,不同平台有不同实现
* @author 杨尚川
*/ 
public interface SequenceService { 
    /**
     * 获取机器码
     * @return  机器码
     */ 
    public String getSequence();     



其次,定义了一个抽象类,实现了一些通用的功能,如生成MD5摘要、将很长的字符串以固定的位数分割开,以便于人类阅读(如将机器码 71F5DA7F495E7F706D47F3E63DC6349A 每4个一组,以-分割为71F5-DA7F-495E-7F70-6D47-F3E6-3DC6-349A)、利用sigar来生成机器码。这里需要在pom.xml中加入sigar依赖。

Xml代码  收藏代码
<dependency> 
    <groupId>org.fusesource</groupId> 
    <artifactId>sigar</artifactId> 
    <version>1.6.4</version> 
    <exclusions> 
        <exclusion> 
            <groupId>log4j</groupId> 
            <artifactId>log4j</artifactId> 
        </exclusion> 
    </exclusions> 
</dependency> 


Java代码  收藏代码
import org.apdplat.module.system.service.PropertyHolder; 
import org.apdplat.platform.log.APDPlatLogger; 
import org.apdplat.platform.util.ConvertUtils; 
import org.apdplat.platform.util.FileUtils; 
import java.io.File; 
import java.io.UnsupportedEncodingException; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 
import java.util.HashSet; 
import java.util.Properties; 
import java.util.Set; 
import org.apdplat.platform.log.APDPlatLoggerFactory; 
import org.hyperic.sigar.Mem; 
import org.hyperic.sigar.NetFlags; 
import org.hyperic.sigar.NetInterfaceConfig; 
import org.hyperic.sigar.Sigar; 
 
/**
*机器码生成的通用服务
* @author 杨尚川
*/ 
public abstract class AbstractSequenceService   implements SequenceService{ 
    protected final APDPlatLogger LOG = APDPlatLoggerFactory.getAPDPlatLogger(getClass()); 
    /**
     * 对一段String生成MD5摘要信息
     * @param message 要摘要的String
     * @return 生成的MD5摘要信息
     */ 
    protected String getMD5(String message) { 
        message += "{apdplat}"; 
        try { 
            MessageDigest md = MessageDigest.getInstance("MD5"); 
            LOG.debug("MD5摘要长度:" + md.getDigestLength()); 
            byte[] b = md.digest(message.getBytes("utf-8")); 
            String md5 = ConvertUtils.byte2HexString(b)+message.length(); 
            return getSplitString(md5); 
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { 
            LOG.error("MD5摘要失败",e); 
        } 
        return null; 
    } 
    /**
     * 将很长的字符串以固定的位数分割开,以便于人类阅读
     * @param str
     * @return 
     */ 
    protected String getSplitString(String str){  
        return getSplitString(str, "-", 4); 
    } 
    /**
     * 将很长的字符串以固定的位数分割开,以便于人类阅读
     * 如将
     * 71F5DA7F495E7F706D47F3E63DC6349A
     * 以-,每4个一组,则分割为
     * 71F5-DA7F-495E-7F70-6D47-F3E6-3DC6-349A
     * @param str 字符串
     * @param split 分隔符
     * @param length 长度
     * @return 
     */ 
    protected String getSplitString(String str, String split, int length){         
        int len=str.length(); 
        StringBuilder temp=new StringBuilder(); 
        for(int i=0;i<len;i++){ 
            if(i%length==0 && i>0){ 
                temp.append(split); 
            } 
            temp.append(str.charAt(i)); 
        } 
        String[] attrs=temp.toString().split(split); 
        StringBuilder finalMachineCode=new StringBuilder(); 
        for(String attr : attrs){ 
            if(attr.length()==length){ 
                finalMachineCode.append(attr).append(split); 
            } 
        } 
        String result=finalMachineCode.toString().substring(0, finalMachineCode.toString().length()-1); 
        return result; 
    }     
    /**
     * 利用sigar来生成机器码,当然这个实现不是很好,无法获得CPU ID,希望有兴趣的朋友来改进这个实现
     * @param osName 操作系统类型
     * @return 机器码
     */ 
    protected String getSigarSequence(String osName) { 
        try { 
            File libFile = new File(FileUtils.getAbsolutePath("/WEB-INF/lib/"+PropertyHolder.getProperty("libsigar."+osName))); 
            LOG.debug("libsigar."+osName+" : "+libFile.getAbsolutePath()); 
             
            System.load(libFile.getAbsolutePath()); 
            Set<String> result = new HashSet<>(); 
            Sigar sigar = new Sigar(); 
            String[] ifaces = sigar.getNetInterfaceList(); 
            for (String iface : ifaces) { 
                NetInterfaceConfig cfg = sigar.getNetInterfaceConfig(iface);                if (NetFlags.LOOPBACK_ADDRESS.equals(cfg.getAddress()) || (cfg.getFlags() & NetFlags.IFF_LOOPBACK) != 0 
                        || NetFlags.NULL_HWADDR.equals(cfg.getHwaddr())) { 
                    continue; 
                } 
                String mac = cfg.getHwaddr(); 
                result.add(mac); 
                LOG.debug("mac: " + mac); 
            } 
            if(result.size()<1){ 
                return null; 
            } 
            Properties props = System.getProperties(); 
            String javaVersion = props.getProperty("java.version"); 
            result.add(javaVersion); 
            LOG.debug("Java的运行环境版本:    " + javaVersion); 
            String javaVMVersion = props.getProperty("java.vm.version"); 
            result.add(javaVMVersion); 
            LOG.debug("Java的虚拟机实现版本:    " + props.getProperty("java.vm.version")); 
            String osVersion = props.getProperty("os.version"); 
            result.add(osVersion); 
            LOG.debug("操作系统的版本:    " + props.getProperty("os.version")); 
 
            Mem mem = sigar.getMem(); 
            // 内存总量 
            String totalMem = mem.getTotal() / 1024L + "K av"; 
            LOG.debug("内存总量:    " + totalMem); 
            result.add(totalMem); 
 
            LOG.debug("result:    " + result); 
            String machineCode = getMD5(result.toString()); 
 
            return machineCode; 
        } catch (Throwable ex) { 
            LOG.error("生成 "+osName+" 平台下的机器码失败", ex); 
        } 
        return null; 
    } 



最后,我们分别看看不同平台的实现。

Windows:

Java代码  收藏代码
/**
*在Windows平台上生成机器码
* @author 杨尚川
*/ 
public final class WindowsSequenceService extends AbstractSequenceService{     
    @Override 
    public String getSequence() {         
        String cpuID=getCPUSerial(); 
        String hdID=getHDSerial("C"); 
        if(cpuID==null || hdID==null){ 
            return null; 
        } 
        String machineCode = getMD5(cpuID+hdID); 
                 
        return machineCode; 
    } 
     
    /**
     *
     * @param drive 硬盘驱动器分区 如C,D
     * @return 该分区的卷标
     */ 
    private String getHDSerial(String drive) { 
        StringBuilder result = new StringBuilder(); 
        try { 
            File file = File.createTempFile("tmp", ".vbs"); 
            file.deleteOnExit(); 
            try (FileWriter fw = new java.io.FileWriter(file)) { 
                String vbs = "Set objFSO = CreateObject(\"Scripting.FileSystemObject\")\n" 
                        + "Set colDrives = objFSO.Drives\n" + "Set objDrive = colDrives.item(\"" + drive + "\")\n" 
                        + "Wscript.Echo objDrive.SerialNumber"; 
                fw.write(vbs); 
            } 
            Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath()); 
            try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()))) { 
                String line; 
                while ((line = input.readLine()) != null) { 
                    result.append(line); 
                } 
            } 
            file.delete(); 
        } catch (Throwable e) { 
            LOG.error("生成HDSerial失败", e); 
        } 
        if (result.length() < 1) { 
            LOG.info("无磁盘ID被读取"); 
        } 
 
        return result.toString(); 
    } 
 
    /**
     * 获取CPU号,多CPU时,只取第一个
     * @return
     */ 
    private String getCPUSerial() { 
        StringBuilder result = new StringBuilder(); 
        try { 
            File file = File.createTempFile("tmp", ".vbs"); 
            file.deleteOnExit(); 
            try (FileWriter fw = new FileWriter(file)) { 
                String vbs = "On Error Resume Next \r\n\r\n" + "strComputer = \".\"  \r\n" 
                        + "Set objWMIService = GetObject(\"winmgmts:\" _ \r\n" 
                        + "    & \"{impersonationLevel=impersonate}!\\\\\" & strComputer & \"\\root\\cimv2\") \r\n" 
                        + "Set colItems = objWMIService.ExecQuery(\"Select * from Win32_Processor\")  \r\n " 
                        + "For Each objItem in colItems\r\n " + "    Wscript.Echo objItem.ProcessorId  \r\n " 
                        + "    exit for  ' do the first cpu only! \r\n" + "Next                    "; 
 
                fw.write(vbs); 
            } 
            Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath()); 
            try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()))) { 
                String line; 
                while ((line = input.readLine()) != null) { 
                    result.append(line); 
                } 
            } 
            file.delete(); 
        } catch (Throwable e) { 
            LOG.error("生成CPUSerial失败", e); 
        } 
        if (result.length() < 1) { 
            LOG.info("无CPU_ID被读取"); 
        } 
        return result.toString(); 
    } 
     
    public static void main(String[] args) {         
        SequenceService s = new WindowsSequenceService(); 
        String seq = s.getSequence(); 
        System.out.println(seq); 
    } 



Linux:

Java代码  收藏代码
/**
*在Linux平台上生成机器码
* @author 杨尚川
*/ 
public class LinuxSequenceService  extends AbstractSequenceService{ 
    @Override 
    public String getSequence() { 
        return getSigarSequence("linux"); 
    } 
 
    public static void main(String[] args) { 
        SequenceService s = new LinuxSequenceService(); 
        String seq = s.getSequence(); 
        System.out.println(seq); 
    } 



Mac OS X:

Java代码  收藏代码
/**
*在Mac OS X平台上生成机器码
* @author 杨尚川
*/ 
public class MacSequenceService    extends AbstractSequenceService{ 
    @Override 
    public String getSequence() { 
        return getSigarSequence("mac"); 
    } 
    
    public static void main(String[] args) { 
        SequenceService s = new MacSequenceService(); 
        String seq = s.getSequence(); 
        System.out.println(seq); 
    } 



Solaris:

Java代码  收藏代码
/**
*在Solaris平台上生成机器码
* @author 杨尚川
*/ 
public class SolarisSequenceService    extends AbstractSequenceService{ 
    @Override 
    public String getSequence() { 
        return getSigarSequence("solaris"); 
    } 
 
    public static void main(String[] args) { 
        SequenceService s = new SolarisSequenceService(); 
        String seq = s.getSequence(); 
        System.out.println(seq); 
    }     



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [java 机器码] 推荐:

(转)JAVA获得机器码的实现

- - jackyrong
首先,定义了一个统一的接口,以支持不同操作系统不同实现的透明切换:. *生成机器码的接口,不同平台有不同实现. * @author 杨尚川.      * 获取机器码.      * @return  机器码. 其次,定义了一个抽象类,实现了一些通用的功能,如生成MD5摘要、将很长的字符串以固定的位数分割开,以便于人类阅读(如将机器码 71F5DA7F495E7F706D47F3E63DC6349A 每4个一组,以-分割为71F5-DA7F-495E-7F70-6D47-F3E6-3DC6-349A)、利用sigar来生成机器码.

Java中的锁(Locks in Java)

- - 并发编程网 - ifeve.com
原文链接 作者:Jakob Jenkov 译者:申章 校对:丁一. 锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂. 因为锁(以及其它更高级的线程同步机制)是由synchronized同步块的方式实现的,所以我们还不能完全摆脱synchronized关键字( 译者注:这说的是Java 5之前的情况).

Java PaaS 对决

- 呆瓜 - IBM developerWorks 中国 : 文档库
本文为 Java 开发人员比较了三种主要的 Platform as a Service (PaaS) 产品:Google App Engine for Java、Amazon Elastic Beanstalk 和 CloudBees RUN@Cloud. 它分析了每种服务独特的技术方法、优点以及缺点,而且还讨论了常见的解决方法.

Java浮点数

- d0ngd0ng - 译言-电脑/网络/数码科技
Thomas Wang, 2000年3月. Java浮点数的定义大体上遵守了二进制浮点运算标准(即IEEE 754标准). IEEE 754标准提供了浮点数无穷,负无穷,负零和非数字(Not a number,简称NaN)的定义. 在Java开发方面,这些东西经常被多数程序员混淆. 在本文中,我们将讨论计算这些特殊的浮点数相关的结果.

Qt——转战Java?

- - 博客 - 伯乐在线
编者按:事实上,在跨平台开发方面,Qt仍是最好的工具之一,无可厚非,但Qt目前没有得到任何主流移动操作系统的正式支持. 诺基亚的未来计划,定位非常模糊,这也是令很多第三方开发者感到失望,因此将导致诺基亚屡遭失败的原因. Qt的主要开发者之一Mirko Boehm在博客上强烈讽刺Nokia裁了Qt部门的决定,称其为“绝望之举”,而非“策略变更”.

java 验证码

- - ITeye博客
// 创建字体,字体的大小应该根据图片的高度来定. // 随机产生160条干扰线,使图象中的认证码不易被其它程序探测到. // randomCode用于保存随机产生的验证码,以便用户登录后进行验证. // 随机产生codeCount数字的验证码. // 得到随机产生的验证码数字. // 产生随机的颜色分量来构造颜色值,这样输出的每位数字的颜色值都将不同.

Java异常

- - CSDN博客推荐文章
“好的程序设计语言能够帮助程序员写出好程序,但是无论哪种语言都避免不了程序员写出坏的程序.                                                                                                                          ----《Java编程思想》.

java面试题

- - Java - 编程语言 - ITeye博客
 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面. 抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节. 抽象包括两个方面,一是过程抽象,二是数据抽象.  继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法. 对象的一个新类可以从现有的类中派生,这个过程称为类继承.

Java使用memcached

- - 互联网 - ITeye博客
首先到 http://danga.com/memcached下载memcached的windows版本和java客户端jar包,目前最新版本是memcached-1.2.1-win32.zip和java_memcached-release_1.6.zip,分别解压后即可. 然后是安装运行memcached服务器,我们将memcached-1.2.1-win32.zip解压后,进入其目录,然后运行如下命令:c:>;memcached.exe -d install
c:>memcached.exe -l 127.0.0.1 -m 32 -d start.

Java线程池

- - 企业架构 - ITeye博客
线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的. 在jdk1.5之后这一情况有了很大的改观. Jdk1.5之后加入了java.util.concurrent包,这个包中主要介绍java中线程以及线程池的使用. 为我们在开发中处理线程的问题提供了非常大的帮助.