How to get a unique computer identifier in Java (like disk ID or motherboard ID)?

Solution 1:

The problem with MAC address is that there can be many network adapters connected to the computer. Most of the newest ones have two by default (wi-fi + cable). In such situation one would have to know which adapter's MAC address should be used. I tested MAC solution on my system, but I have 4 adapters (cable, WiFi, TAP adapter for Virtual Box and one for Bluetooth) and I was not able to decide which MAC I should take... If one would decide to use adapter which is currently in use (has addresses assigned) then new problem appears since someone can take his/her laptop and switch from cable adapter to wi-fi. With such condition MAC stored when laptop was connected through cable will now be invalid.

For example those are adapters I found in my system:

lo MS TCP Loopback interface
eth0 Intel(R) Centrino(R) Advanced-N 6205
eth1 Intel(R) 82579LM Gigabit Network Connection
eth2 VirtualBox Host-Only Ethernet Adapter
eth3 Sterownik serwera dostepu do sieci LAN Bluetooth

Code I've used to list them:

Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
while (nis.hasMoreElements()) {
    NetworkInterface ni = nis.nextElement();
    System.out.println(ni.getName() + " " + ni.getDisplayName());
}

From the options listen on this page, the most acceptable for me, and the one I've used in my solution is the one by @Ozhan Duz, the other one, similar to @finnw answer where he used JACOB, and worth mentioning is com4j - sample which makes use of WMI is available here:

ISWbemLocator wbemLocator = ClassFactory.createSWbemLocator();
ISWbemServices wbemServices = wbemLocator.connectServer("localhost","Root\\CIMv2","","","","",0,null);
ISWbemObjectSet result = wbemServices.execQuery("Select * from Win32_SystemEnclosure","WQL",16,null);
for(Com4jObject obj : result) {
    ISWbemObject wo = obj.queryInterface(ISWbemObject.class);
    System.out.println(wo.getObjectText_(0));
}

This will print some computer information together with computer Serial Number. Please note that all classes required by this example has to be generated by maven-com4j-plugin. Example configuration for maven-com4j-plugin:

<plugin>
    <groupId>org.jvnet.com4j</groupId>
    <artifactId>maven-com4j-plugin</artifactId>
    <version>1.0</version>
    <configuration>
        <libId>565783C6-CB41-11D1-8B02-00600806D9B6</libId>
        <package>win.wmi</package>
        <outputDirectory>${project.build.directory}/generated-sources/com4j</outputDirectory>
    </configuration>
    <executions>
        <execution>
            <id>generate-wmi-bridge</id>
            <goals>
                <goal>gen</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Above's configuration will tell plugin to generate classes in target/generated-sources/com4j directory in the project folder.

For those who would like to see ready-to-use solution, I'm including links to the three classes I wrote to get machine SN on Windows, Linux and Mac OS:

  • Java code to get computer SN on Windows
  • Java code to get computer SN on Linux
  • Java code to get computer SN on Mac OS

Solution 2:

The OSHI project provides platform-independent hardware utilities.

Maven dependency:

<dependency>
    <groupId>com.github.oshi</groupId>
    <artifactId>oshi-core</artifactId>
    <version>LATEST</version>
</dependency>

For instance, you could use something like the following code to identify a machine uniquely:

import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.ComputerSystem;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.OperatingSystem;

class ComputerIdentifier
{
    static String generateLicenseKey()
    {
        SystemInfo systemInfo = new SystemInfo();
        OperatingSystem operatingSystem = systemInfo.getOperatingSystem();
        HardwareAbstractionLayer hardwareAbstractionLayer = systemInfo.getHardware();
        CentralProcessor centralProcessor = hardwareAbstractionLayer.getProcessor();
        ComputerSystem computerSystem = hardwareAbstractionLayer.getComputerSystem();

        String vendor = operatingSystem.getManufacturer();
        String processorSerialNumber = computerSystem.getSerialNumber();
        String processorIdentifier = centralProcessor.getIdentifier();
        int processors = centralProcessor.getLogicalProcessorCount();

        String delimiter = "#";

        return vendor +
                delimiter +
                processorSerialNumber +
                delimiter +
                processorIdentifier +
                delimiter +
                processors;
    }

    public static void main(String[] arguments)
    {
        String identifier = generateLicenseKey();
        System.out.println(identifier);
    }
}

Output for my machine:

Microsoft#57YRD12#Intel64 Family 6 Model 60 Stepping 3#8

Your output will be different since at least the processor serial number will differ.

Solution 3:

It is common to use the MAC address is associated with the network card.

The address is available in Java 6 through through the following API:

Java 6 Docs for Hardware Address

I haven't used it in Java, but for other network identification applications it has been helpful.