[java] Create a GUID in Java

What are some of the best ways to create a GUID in Java?

This question is related to java guid

The answer is


Just to extend Mark Byers's answer with an example:

import java.util.UUID;

public class RandomStringUUID {
    public static void main(String[] args) {
        UUID uuid = UUID.randomUUID();
        System.out.println("UUID=" + uuid.toString() );
    }
}

This answer contains 2 generators for random-based and name-based UUIDs, compliant with RFC-4122. Feel free to use and share.

RANDOM-BASED (v4)

This utility class that generates random-based UUIDs:

package your.package.name;

import java.security.SecureRandom;
import java.util.Random;
import java.util.UUID;

/**
 * Utility class that creates random-based UUIDs.
 * 
 */
public abstract class RandomUuidCreator {

    private static final int RANDOM_VERSION = 4;

    /**
     * Returns a random-based UUID.
     * 
     * It uses a thread local {@link SecureRandom}.
     * 
     * @return a random-based UUID
     */
    public static UUID getRandomUuid() {
        return getRandomUuid(SecureRandomLazyHolder.THREAD_LOCAL_RANDOM.get());
    }

    /**
     * Returns a random-based UUID.
     * 
     * It uses any instance of {@link Random}.
     * 
     * @return a random-based UUID
     */
    public static UUID getRandomUuid(Random random) {

        long msb = 0;
        long lsb = 0;

        // (3) set all bit randomly
        if (random instanceof SecureRandom) {
            // Faster for instances of SecureRandom
            final byte[] bytes = new byte[16];
            random.nextBytes(bytes);
            msb = toNumber(bytes, 0, 8); // first 8 bytes for MSB
            lsb = toNumber(bytes, 8, 16); // last 8 bytes for LSB
        } else {
            msb = random.nextLong(); // first 8 bytes for MSB
            lsb = random.nextLong(); // last 8 bytes for LSB
        }

        // Apply version and variant bits (required for RFC-4122 compliance)
        msb = (msb & 0xffffffffffff0fffL) | (RANDOM_VERSION & 0x0f) << 12; // apply version bits
        lsb = (lsb & 0x3fffffffffffffffL) | 0x8000000000000000L; // apply variant bits

        // Return the UUID
        return new UUID(msb, lsb);
    }

    private static long toNumber(final byte[] bytes, final int start, final int length) {
        long result = 0;
        for (int i = start; i < length; i++) {
            result = (result << 8) | (bytes[i] & 0xff);
        }
        return result;
    }

    // Holds thread local secure random
    private static class SecureRandomLazyHolder {
        static final ThreadLocal<Random> THREAD_LOCAL_RANDOM = ThreadLocal.withInitial(SecureRandom::new);
    }

    /**
     * For tests!
     */
    public static void main(String[] args) {

        System.out.println("// Using thread local `java.security.SecureRandom` (DEFAULT)");
        System.out.println("RandomUuidCreator.getRandomUuid()");
        System.out.println();
        for (int i = 0; i < 5; i++) {
            System.out.println(RandomUuidCreator.getRandomUuid());
        }

        System.out.println();
        System.out.println("// Using `java.util.Random` (FASTER)");
        System.out.println("RandomUuidCreator.getRandomUuid(new Random())");
        System.out.println();
        Random random = new Random();
        for (int i = 0; i < 5; i++) {
            System.out.println(RandomUuidCreator.getRandomUuid(random));
        }
    }
}

This is the output:

// Using thread local `java.security.SecureRandom` (DEFAULT)
RandomUuidCreator.getRandomUuid()

'ef4f5ad2-8147-46cb-8389-c2b8c3ef6b10'
'adc0305a-df29-4f08-9d73-800fde2048f0'
'4b794b59-bff8-4013-b656-5d34c33f4ce3'
'22517093-ee24-4120-96a5-ecee943992d1'
'899fb1fb-3e3d-4026-85a8-8a2d274a10cb'

// Using `java.util.Random` (FASTER)
RandomUuidCreator.getRandomUuid(new Random())

'4dabbbc2-fcb2-4074-a91c-5e2977a5bbf8'
'078ec231-88bc-4d74-9774-96c0b820ceda'
'726638fa-69a6-4a18-b09f-5fd2a708059b'
'15616ebe-1dfd-4f5c-b2ed-cea0ac1ad823'
'affa31ad-5e55-4cde-8232-cddd4931923a'

NAME-BASED (v3 and v5)

This utility class that generates name-based UUIDs (MD5 and SHA1):

package your.package.name;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

/**
 * Utility class that creates UUIDv3 (MD5) and UUIDv5 (SHA1).
 *
 */
public class HashUuidCreator {

    // Domain Name System
    public static final UUID NAMESPACE_DNS = new UUID(0x6ba7b8109dad11d1L, 0x80b400c04fd430c8L);
    // Uniform Resource Locator
    public static final UUID NAMESPACE_URL = new UUID(0x6ba7b8119dad11d1L, 0x80b400c04fd430c8L);
    // ISO Object ID
    public static final UUID NAMESPACE_ISO_OID = new UUID(0x6ba7b8129dad11d1L, 0x80b400c04fd430c8L);
    // X.500 Distinguished Name
    public static final UUID NAMESPACE_X500_DN = new UUID(0x6ba7b8149dad11d1L, 0x80b400c04fd430c8L);

    private static final int VERSION_3 = 3; // UUIDv3 MD5
    private static final int VERSION_5 = 5; // UUIDv5 SHA1

    private static final String MESSAGE_DIGEST_MD5 = "MD5"; // UUIDv3
    private static final String MESSAGE_DIGEST_SHA1 = "SHA-1"; // UUIDv5

    private static UUID getHashUuid(UUID namespace, String name, String algorithm, int version) {

        final byte[] hash;
        final MessageDigest hasher;

        try {
            // Instantiate a message digest for the chosen algorithm
            hasher = MessageDigest.getInstance(algorithm);

            // Insert name space if NOT NULL
            if (namespace != null) {
                hasher.update(toBytes(namespace.getMostSignificantBits()));
                hasher.update(toBytes(namespace.getLeastSignificantBits()));
            }

            // Generate the hash
            hash = hasher.digest(name.getBytes(StandardCharsets.UTF_8));

            // Split the hash into two parts: MSB and LSB
            long msb = toNumber(hash, 0, 8); // first 8 bytes for MSB
            long lsb = toNumber(hash, 8, 16); // last 8 bytes for LSB

            // Apply version and variant bits (required for RFC-4122 compliance)
            msb = (msb & 0xffffffffffff0fffL) | (version & 0x0f) << 12; // apply version bits
            lsb = (lsb & 0x3fffffffffffffffL) | 0x8000000000000000L; // apply variant bits

            // Return the UUID
            return new UUID(msb, lsb);

        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Message digest algorithm not supported.");
        }
    }

    public static UUID getMd5Uuid(String string) {
        return getHashUuid(null, string, MESSAGE_DIGEST_MD5, VERSION_3);
    }

    public static UUID getSha1Uuid(String string) {
        return getHashUuid(null, string, MESSAGE_DIGEST_SHA1, VERSION_5);
    }

    public static UUID getMd5Uuid(UUID namespace, String string) {
        return getHashUuid(namespace, string, MESSAGE_DIGEST_MD5, VERSION_3);
    }

    public static UUID getSha1Uuid(UUID namespace, String string) {
        return getHashUuid(namespace, string, MESSAGE_DIGEST_SHA1, VERSION_5);
    }

    private static byte[] toBytes(final long number) {
        return new byte[] { (byte) (number >>> 56), (byte) (number >>> 48), (byte) (number >>> 40),
                (byte) (number >>> 32), (byte) (number >>> 24), (byte) (number >>> 16), (byte) (number >>> 8),
                (byte) (number) };
    }

    private static long toNumber(final byte[] bytes, final int start, final int length) {
        long result = 0;
        for (int i = start; i < length; i++) {
            result = (result << 8) | (bytes[i] & 0xff);
        }
        return result;
    }

    /**
     * For tests!
     */
    public static void main(String[] args) {

        String string = "JUST_A_TEST_STRING";
        UUID namespace = UUID.randomUUID(); // A custom name space

        System.out.println("Java's generator");
        System.out.println("UUID.nameUUIDFromBytes():      '" + UUID.nameUUIDFromBytes(string.getBytes()) + "'");
        System.out.println();
        System.out.println("This generator");
        System.out.println("HashUuidCreator.getMd5Uuid():  '" + HashUuidCreator.getMd5Uuid(string) + "'");
        System.out.println("HashUuidCreator.getSha1Uuid(): '" + HashUuidCreator.getSha1Uuid(string) + "'");
        System.out.println();
        System.out.println("This generator WITH name space");
        System.out.println("HashUuidCreator.getMd5Uuid():  '" + HashUuidCreator.getMd5Uuid(namespace, string) + "'");
        System.out.println("HashUuidCreator.getSha1Uuid(): '" + HashUuidCreator.getSha1Uuid(namespace, string) + "'");
    }
}

This is the output:

// Java's generator
UUID.nameUUIDFromBytes():      '9e120341-627f-32be-8393-58b5d655b751'

// This generator
HashUuidCreator.getMd5Uuid():  '9e120341-627f-32be-8393-58b5d655b751'
HashUuidCreator.getSha1Uuid(): 'e4586bed-032a-5ae6-9883-331cd94c4ffa'

// This generator WITH name space
HashUuidCreator.getMd5Uuid():  '2b098683-03c9-3ed8-9426-cf5c81ab1f9f'
HashUuidCreator.getSha1Uuid(): '1ef568c7-726b-58cc-a72a-7df173463bbb'

ALTERNATE GENERATOR

You can also use the uuid-creator library. See these examples:

// Create a random-based UUID
UUID uuid = UuidCreator.getRandomBased();
// Create a name based UUID (SHA1)
String name = "JUST_A_TEST_STRING";
UUID uuid = UuidCreator.getNameBasedSha1(name);

Project page: https://github.com/f4b6a3/uuid-creator


It depends what kind of UUID you want.

  • The standard Java UUID class generates Version 4 (random) UUIDs. (UPDATE - Version 3 (name) UUIDs can also be generated.) It can also handle other variants, though it cannot generate them. (In this case, "handle" means construct UUID instances from long, byte[] or String representations, and provide some appropriate accessors.)

  • The Java UUID Generator (JUG) implementation purports to support "all 3 'official' types of UUID as defined by RFC-4122" ... though the RFC actually defines 4 types and mentions a 5th type.

For more information on UUID types and variants, there is a good summary in Wikipedia, and the gory details are in RFC 4122 and the other specifications.


java.util.UUID.randomUUID();


The other Answers are correct, especially this one by Stephen C.

Reaching Outside Java

Generating a UUID value within Java is limited to Version 4 (random) because of security concerns.

If you want other versions of UUIDs, one avenue is to have your Java app reach outside the JVM to generate UUIDs by calling on:

  • Command-line utility
    Bundled with nearly every operating system.
    For example, uuidgen found in Mac OS X, BSD, and Linux.
  • Database server
    Use JDBC to retrieve a UUID generated on the database server.
    For example, the uuid-ossp extension often bundled with Postgres. That extension can generates Versions 1, 3, and 4 values and additionally a couple variations:
    • uuid_generate_v1mc() – generates a version 1 UUID but uses a random multicast MAC address instead of the real MAC address of the computer.
    • uuid_generate_v5(namespace uuid, name text) – generates a version 5 UUID, which works like a version 3 UUID except that SHA-1 is used as a hashing method.
  • Web Service
    For example, UUID Generator creates Versions 1 & 3 as well as nil values and GUID.