The Java docs about java.util.UUID talk about the UUID variants, with special emphasis on variant 2, "IETF RFC 4122 (Leach-Salz), used by this class", even has a method to inquire the variant of a given UUID, but it has no constructor or static generator method which would actually give you a variant 2 UUID value. If not even the JVM can interface to our OS to inquire the ethernet address to use, then what else possibly could in any portable manner? And if variant 2 is simply not provided by the java.util.UUID, then why would the documentation go on about it? That's a rhetorical question of course. I don't care knowing a conjecture of motives. What I really care about is to know if perhaps I am overlooking the obvious solution, or is there some known portable way to generate a real variant 2 UUID in Java?
Apparently there is a confusion about "version" and "variant" and "types" and what this class does and doesn't do.
The documentation says:
Variant
There exist different variants of these global identifiers. The methods of this class are for manipulating the Leach-Salz variant, although the constructors allow the creation of any variant of UUID (described below).
The variant number associated with this UUID. The variant number describes the layout of the UUID. The variant number has the following meaning: 0 Reserved for NCS backward compatibility 2 IETF RFC 4122 (Leach-Salz), used by this class 6 Reserved, Microsoft Corporation backward compatibility 7 Reserved for future definition
Version
0x000000000000F000 version [mask]
The version field holds a value that describes the type of this UUID. There are four different basic types of UUIDs: time-based, DCE security, name-based, and randomly generated UUIDs. These types have a version value of 1, 2, 3 and 4, respectively.
Type (apparently synonym of "version")
- type 4 (pseudo randomly generated) UUID
- type 3 (name based) UUID
- timestamp value is only meaningful in a time-based UUID, which has version type 1
- time-based UUID, which has version type 1
Regardless, there is no constructor method or static generator method to create one. If there was one that could be named. The one suggestion nameUUIDFromBytes offered is not a generator of a UUID but simply an encoder given a byte array the caller must supply.
The only generator there is is for randomUUID (variant 4). The other methods are just encoders where you must supply the distinguishing argument.
To test this all out and get away from speculation, here is code:
import java.util.UUID;
public class MyClass {
public static final byte uuidBytes1[] = { };
public static final byte uuidBytes2[] = { 0x00, 0x00, 0x00, 0x00 };
public static void main(String args[]) {
printUUID(UUID.randomUUID());
printUUID(UUID.randomUUID());
printUUID(UUID.randomUUID());
printUUID(UUID.randomUUID());
printUUID(UUID.nameUUIDFromBytes(uuidBytes1));
printUUID(UUID.nameUUIDFromBytes(uuidBytes1));
printUUID(UUID.nameUUIDFromBytes(uuidBytes2));
printUUID(UUID.nameUUIDFromBytes(uuidBytes2));
printUUID(UUID.fromString("00000000-0000-0000-0000-000000000000"));
printUUID(UUID.fromString("48ad35a5-3efc-11ed-a8a4-c543706c92cc"));
printUUID(UUID.fromString("b0c28760-3f0d-11ed-98d6-54ee7566e1cf"));
}
static void printUUID(UUID uuid) {
System.out.println(uuid.toString() + " version=" + uuid.version() + " variant=" + uuid.variant());
}
}
gives:
cb290caa-4c90-4fd5-bd9e-18292a1257b1 version=4 variant=2
3fb0e827-8d68-45dc-bba0-079c5756eaef version=4 variant=2
8a2e173c-5c9d-4037-b6a0-d30dbd89fd98 version=4 variant=2
29b38a93-06c9-4676-a167-337292d6f086 version=4 variant=2
d41d8cd9-8f00-3204-a980-0998ecf8427e version=3 variant=2
d41d8cd9-8f00-3204-a980-0998ecf8427e version=3 variant=2
f1d3ff84-4329-3732-862d-f21dc4e57262 version=3 variant=2
f1d3ff84-4329-3732-862d-f21dc4e57262 version=3 variant=2
00000000-0000-0000-0000-000000000000 version=0 variant=0
48ad35a5-3efc-11ed-a8a4-c543706c92cc version=1 variant=2
b0c28760-3f0d-11ed-98d6-54ee7566e1cf version=1 variant=2
You see that only random UUIDs generate a new UUID when called twice. But it is not the time based and ethernet interface address based kind (call it version, variant, or type, I don't care.)
Here, for contrast, is what FreeBSD's uuidgen program gives me:
$ uuidgen -n 4
45430d23-3efc-11ed-a8a4-c543706c92cc
45430d24-3efc-11ed-a8a4-c543706c92cc
45430d25-3efc-11ed-a8a4-c543706c92cc
45430d26-3efc-11ed-a8a4-c543706c92cc
$ uuidgen -n 4
46cd5a7f-3efc-11ed-a8a4-c543706c92cc
46cd5a80-3efc-11ed-a8a4-c543706c92cc
46cd5a81-3efc-11ed-a8a4-c543706c92cc
46cd5a82-3efc-11ed-a8a4-c543706c92cc
$ uuidgen -n 4
48ad35a2-3efc-11ed-a8a4-c543706c92cc
48ad35a3-3efc-11ed-a8a4-c543706c92cc
48ad35a4-3efc-11ed-a8a4-c543706c92cc
48ad35a5-3efc-11ed-a8a4-c543706c92cc
You can see that in 4 runs requesting batches of 4 UUIDs, I get a different one every time, but also you see that what supposedly is one of my ethernet interface, with ifconfig I see a 12:f3:c3:3c:b0:e6, but not a c543706c92cc
On my laptop with cygwin, I get this:
$ uuidgen -t
b0c28760-3f0d-11ed-98d6-54ee7566e1cf
$ uuidgen -t
b1adda44-3f0d-11ed-95a4-54ee7566e1cf
$ uuidgen -t
b2df28b4-3f0d-11ed-89aa-54ee7566e1cf
$ uuidgen -t
b389dcb4-3f0d-11ed-b93d-54ee7566e1cf
and it matched ipconfig:
Ethernet adapter Ethernet 4:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :
Description . . . . . . . . . . . : Intel(R) Ethernet Connection (3) I218-LM
Physical Address. . . . . . . . . : 54-EE-75-66-E1-CF
DHCP Enabled. . . . . . . . . . . : Yes
Autoconfiguration Enabled . . . . : Yes
And this is what I want from Java. Because I want to get away from all those random UUIDs. By the time I have 100s of millions of those generated, I am beginning to worry about collisions.
So, how can I get one of those ethernet and time based UUIDs?