4 January 2005
java.util.UUID mini-FAQ

J2SE 1.5 gives us a new class to generate identifiers. Here are some details I found after writing a bit of code and doing some reading.

What is a UUID?

According to Wikipedia:

“…an identifier standard used in software construction, standardized by the Open Software Foundation (OSF) as part of the Distributed Computing Environment (DCE). The intent of UUIDs is to enable distributed systems to uniquely identify information without significant central coordination. Thus, anyone can create a UUID and use it to identify something with reasonable confidence that that identifier will never be unintentionally used by anyone for anything else. Information labelled with UUIDs can therefore be later combined into a single database without need to resolve name conflicts. The most widespread use of this standard is in Microsoft’s Globally Unique Identifiers (GUIDs) which implement this standard.

A UUID is essentially a 16-byte number and in its canonical form a UUID may look like this:

550E8400-E29B-11D4-A716-446655440000

How do I generate a new UUID?

Calling the randomUUID() factory method will give you a fresh instance. Calling toString() will provide a spec-compliant canonical string representation. See the testRandom method in the source below.

I thought these were called GUIDs. What is a UUID?

Per the draft spec referenced below these are synonymous:

…UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally
Unique IDentifier).

I’m a Windows guy. Is this the same thing as CoCreateGuid?

According to MSDN the current version of CoCreateGuid also generates a ‘version 4′ random number based UUID.

The CoCreateGuid function calls the RPC function UuidCreate, which creates a GUID, a globally unique 128-bit integer. Use the CoCreateGuid function when you need an absolutely unique number that you will use as a persistent identifier in a distributed environment.To a very high degree of certainty, this function returns a unique value no other invocation, on the same or any other system (networked or not), should return the same value.

For security reasons, it is often desirable to keep ethernet/token ring addresses on networks from becoming available outside a company or organization. In Windows XP/2000, the UuidCreate function generates a UUID that cannot be traced to the ethernet/token ring address of the computer on which it was generated. It also cannot be associated with other UUIDs created on the same computer. If you do not need this level of security, your application can use the UuidCreateSequential function, which behaves exactly as the UuidCreate function does on all other versions of the operating system.

In Windows NT 4.0, Windows 95, DCOM release, and Windows 98, UuidCreate returns RPC_S_UUID_LOCAL_ONLY when the originating computer does not have an ethernet/token ring (IEEE 802.x) address. In this case, the generated UUID is a valid identifier, and is guaranteed to be unique among all UUIDs generated on the computer. However, the possibility exists that another computer without an ethernet/token ring address generated the identical UUID. Therefore you should never use this UUID to identify an object that is not strictly local to your computer. Computers with ethernet/token ring addresses generate UUIDs that are guaranteed to be globally unique.

I thought UUIDs used the MAC address to guarantee uniqueness

The specification defines multiple types of UUIDs. Version 1 UUIDs include a MAC address. Version 4 UUIDs are generated from a large random number and do not include the MAC address. The implementation of java.util.UUID creates version 4 UUIDs. See the testVersion method in the source below.

So java.util.UUID can only generate version 4 UUIDs. Can it parse and handle the other types?

Yes. Using the fromString method you can instantiate and interrogate a UUID of version 1,2,3 or 4. See the testFromString method in the source below; note it’s a version 1 UUID.

The draft spec talks about multiple variant types of UUIDs. Which variant types are supported by java.util.UUID?

As indicated by the javadoc for getVariant(), java.util.UUID only supports variant type 2.

I like the idea of using the MAC address. What makes version 4 UUIDs better?

Using a version 4 UUID could save you 20 months in a United States Federal Prison. Evidently the writer of the Melissa worm was tracked down in part by the MAC address in a UUID.

So these version 4 UUIDs are basically random numbers. Won’t my UUID collide with someone elses?

There are 122 significant bits in a type 4 UUID. 2122 is a *very* large number. Assuming a random distribution of these bits, the probability of collission is *very* low. How is the “randomness” determined?

Under the hood java.util.UUID is creating an instance of SecureRandom and using that to generate new UUIDs. If you are using the default Sun provider and default java.security file, you are using a SHA1PRNG ( Pseudo Random Number Generator based on Secure Hash Algorigthm 1 ) seeded from the operating system.

java.security

#
# Select the source of seed data for SecureRandom. By default an
# attempt is made to use the entropy gathering device specified by
# the securerandom.source property. If an exception occurs when
# accessing the URL then the traditional system/thread activity
# algorithm is used.
#
# On Solaris and Linux systems, if file:/dev/urandom is specified and it
# exists, a special SecureRandom implementation is activated by default.
# This "NativePRNG" reads random bytes directly from /dev/urandom.
#
# On Windows systems, the URLs file:/dev/random and file:/dev/urandom
# enables use of the Microsoft CryptoAPI seed functionality.
#
securerandom.source=file:/dev/urandom

On WinTel platforms this may map down to hardware

More on randomness

I want to preserve backward JDK compatibilty. I’ll just use java.rmi.server.UID. Cool?

Probably a bad idea. Per the docs this gives you 216 significant digits. It is also makes no provision for the system clock being set backward.

What other options do I have?

commons-id is a general purpose identifier generator capable of generating UUIDs.

Where can I read more about UUIDs?

Current Draft Specification

Sample Code

import java.util.UUID;
  import junit.framework.TestCase;
public class UUIDTest extends TestCase {  	
	public void testRandom() { 		
		UUID a = UUID.randomUUID();
		UUID b = UUID.randomUUID();
		assertFalse(a.equals(b));
	}  	

	public void testVariant() { 		
		UUID a = UUID.randomUUID();
		assertEquals(a.variant(), 2);
	}  	

	public void testVersion() { 		
		UUID a1 = UUID.randomUUID();
		assertEquals(a1.version(), 4);
		// here is a version 1 UUID plucked from my own HKLMSoftwareClasses 		
		// for history of UUIDs ending in 444553540000 		
		// http://blogs.msdn.com/oldnewthing/archive/2004/02/11/71307.aspx#71356 		
		UUID a2 = UUID.fromString("d27cdb6e-ae6d-11cf-96b8-444553540000");
		assertEquals(a2.variant(), 2);
		assertEquals(a2.version(), 1);
	}  	

	public void testFromString() { 		
		String s = "d27cdb6e-ae6d-11cf-96b8-444553540000";
		UUID a = UUID.fromString(s);
		assertEquals(a.toString(), s);
	}  	

	public void testVersionFromCommonsTestCase() {  		
		// these UUIDs are from commons-id 		
		UUID v1 = UUID.fromString("3051a8d7-aea7-1801-e0bf-bc539dd60cf3");
		UUID v2 = UUID.fromString("3051a8d7-aea7-2801-e0bf-bc539dd60cf3");
		UUID v3 = UUID.fromString("3051a8d7-aea7-3801-e0bf-bc539dd60cf3");
		UUID v4 = UUID.fromString("3051a8d7-aea7-4801-e0bf-bc539dd60cf3");

		//UUID v5 = UUID.fromString("3051a8d7-aea7-3801-e0bf-bc539dd60cf3");
		assertEquals(1, v1.version());
		assertEquals(2, v2.version());
		assertEquals(3, v3.version());
		assertEquals(4, v4.version());

		// java.util.UUID doesn't support version 5 UUIDs while commons-id does 		
		//assertEquals(5, v5.version());
	} 
}
← Read More