Summary
Introduce a static factory method UUID.timestampUUID() to generate Version 7 UUIDs as defined in RFC 9562 using a millisecond precision Unix timestamp with sub-millisecond extra percision.
Problem
The JDK currently supports version 3 and version 4 UUIDs via UUID.nameUUIDFromBytes() and UUID.randomUUID(), but does not provide built-in support for generating time-based version 7 UUIDs. UUIDv7 provides unique identifiers which can be sorted by creation time and has been of increasing popularity especialy in distributed systems.
Solution
Add a static factory method UUID.timestampUUID() to the java.util.UUID class. This method generates a Version 7 UUID by embedding the current Unix timestamp in ms into the first 48 bits, sets the version and variant fields according to RFC 9562, and uses a combination of sub ms time-derived bits and pseudorandom data to populate the remaining bits. Alternative approaches without the additional sub-ms time enhancement aswel as a counter-based approach were also considered but fell short in the percision/performance trade-off.
Specification
Update UUID.java spec with the following:
diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java
index 08b9b87b7ca..0d3d4045d7e 100644
--- a/src/java.base/share/classes/java/util/UUID.java
+++ b/src/java.base/share/classes/java/util/UUID.java
@@ -61,10 +61,10 @@
* {@code UUID}. The bit layout described above is valid only for a {@code
* UUID} with a variant value of 2, which indicates the Leach-Salz variant.
*
- * <p> The version field holds a value that describes the type of this {@code
- * 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.
+ * <p> There are eight defined types of UUIDs, each identified by a version number:
+ * time-based (version 1), DCE security (version 2), name-based with MD5 (version 3),
+ * randomly generated (version 4), name-based with SHA-1 (version 5), reordered time-based (version 6),
+ * Unix epoch time-based (version 7), and custom-defined layout (version 8).
*
* <p> For more information including algorithms used to create {@code UUID}s,
* see <a href="http://www.ietf.org/rfc/rfc4122.txt"> <i>RFC 4122: A
@@ -181,6 +181,44 @@ public static UUID nameUUIDFromBytes(byte[] name) {
return new UUID(md5Bytes);
}
+ /**
+ * Static factory to retrieve a type 7 (time based) {@code UUID} based on
+ * the current timestamp, enhanced with sub-millisecond precision.
+ *
+ * The {@code UUID} embeds the current Unix timestamp in milliseconds into
+ * the first 6 bytes, sets the version and variant bits as per RFC 9562,
+ * replaces the first 12 random bits with a value derived from the current
+ * system clock's sub-millisecond precision, and fills the
+ * remaining bytes with cryptographically strong random data.
+ *
+ * @return A {@code UUID} generated from the current system time
+ */
+ public static UUID timestampUUID() {
+ long msTime = System.currentTimeMillis();
+ long nsTime = System.nanoTime();
+ SecureRandom ng = Holder.numberGenerator;
+ byte[] randomBytes = new byte[16];
+ ng.nextBytes(randomBytes);
+
+ // Set the first 6 bytes to the ms time
+ for (int i = 0; i < 6; i++) {
+ randomBytes[i] = (byte) (msTime >>> (40 - 8 * i));
+ }
+
+ // Scale sub-ms nanoseconds to a 12-bit value
+ int nsBits = (int) ((nsTime % 1_000_000) / 1_000_000.0 * 4096);
+
+ // Set version and increased percision time bits
+ randomBytes[6] = (byte) (0x70 | ((nsBits >>> 8) & 0x0F));
+ randomBytes[7] = (byte) (nsBits & 0xFF);
+
+ // Set variant to 2
+ randomBytes[8] &= 0x3F;
+ randomBytes[8] |= (byte) 0x80;
+
+ return new UUID(randomBytes);
+ }
+
private static final byte[] NIBBLES;
static {
byte[] ns = new byte[256];
@@ -323,6 +361,7 @@ public long getMostSignificantBits() {
* <li>2 DCE security UUID
* <li>3 Name-based UUID
* <li>4 Randomly generated UUID
+ * <li>7 Unix timestamp-based UUID
* </ul>
*
* @return The version number of this {@code UUID}
@@ -481,7 +520,7 @@ public String toString() {
HexDigits.put4(buf, 28, i3 >> 16);
HexDigits.put4(buf, 32, i3);
try {
- return jla.uncheckedNewStringNoRepl(buf, StandardCharsets.ISO_8859_1);
+ return jla.newStringNoRepl(buf, StandardCharsets.ISO_8859_1);
} catch (CharacterCodingException cce) {
throw new AssertionError(cce);
}
- csr of
-
JDK-8334015 Add Support for UUID Version 7 (UUIDv7) defined in RFC 9562
-
- Open
-