8006627: UUID to/from String performance should be improved by reducing object allocations
Co-authored-by: Steven Schlansker <stevenschlansker@gmail.com> Reviewed-by: mduigou, plevart
This commit is contained in:
parent
744f8147ae
commit
23f341125f
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -27,6 +27,9 @@ package java.util;
|
|||||||
|
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
|
|
||||||
|
import sun.misc.JavaLangAccess;
|
||||||
|
import sun.misc.SharedSecrets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that represents an immutable universally unique identifier (UUID).
|
* A class that represents an immutable universally unique identifier (UUID).
|
||||||
* A UUID represents a 128-bit value.
|
* A UUID represents a 128-bit value.
|
||||||
@ -88,6 +91,8 @@ public final class UUID implements java.io.Serializable, Comparable<UUID> {
|
|||||||
*/
|
*/
|
||||||
private final long leastSigBits;
|
private final long leastSigBits;
|
||||||
|
|
||||||
|
private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The random number generator used by this class to create random
|
* The random number generator used by this class to create random
|
||||||
* based UUIDs. In a holder class to defer initialization until needed.
|
* based UUIDs. In a holder class to defer initialization until needed.
|
||||||
@ -189,21 +194,35 @@ public final class UUID implements java.io.Serializable, Comparable<UUID> {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static UUID fromString(String name) {
|
public static UUID fromString(String name) {
|
||||||
String[] components = name.split("-");
|
if (name.length() > 36) {
|
||||||
if (components.length != 5)
|
throw new IllegalArgumentException("UUID string too large");
|
||||||
|
}
|
||||||
|
|
||||||
|
int dash1 = name.indexOf('-', 0);
|
||||||
|
int dash2 = name.indexOf('-', dash1 + 1);
|
||||||
|
int dash3 = name.indexOf('-', dash2 + 1);
|
||||||
|
int dash4 = name.indexOf('-', dash3 + 1);
|
||||||
|
int dash5 = name.indexOf('-', dash4 + 1);
|
||||||
|
|
||||||
|
// For any valid input, dash1 through dash4 will be positive and dash5
|
||||||
|
// negative, but it's enough to check dash4 and dash5:
|
||||||
|
// - if dash1 is -1, dash4 will be -1
|
||||||
|
// - if dash1 is positive but dash2 is -1, dash4 will be -1
|
||||||
|
// - if dash1 and dash2 is positive, dash3 will be -1, dash4 will be
|
||||||
|
// positive, but so will dash5
|
||||||
|
if (dash4 < 0 || dash5 >= 0) {
|
||||||
throw new IllegalArgumentException("Invalid UUID string: " + name);
|
throw new IllegalArgumentException("Invalid UUID string: " + name);
|
||||||
for (int i=0; i<5; i++)
|
}
|
||||||
components[i] = "0x"+components[i];
|
|
||||||
|
|
||||||
long mostSigBits = Long.decode(components[0]).longValue();
|
long mostSigBits = Long.parseLong(name, 16, 0, dash1) & 0xffffffffL;
|
||||||
mostSigBits <<= 16;
|
mostSigBits <<= 16;
|
||||||
mostSigBits |= Long.decode(components[1]).longValue();
|
mostSigBits |= Long.parseLong(name, 16, dash1 + 1, dash2) & 0xffffL;
|
||||||
mostSigBits <<= 16;
|
mostSigBits <<= 16;
|
||||||
mostSigBits |= Long.decode(components[2]).longValue();
|
mostSigBits |= Long.parseLong(name, 16, dash2 + 1, dash3) & 0xffffL;
|
||||||
|
|
||||||
long leastSigBits = Long.decode(components[3]).longValue();
|
long leastSigBits = Long.parseLong(name, 16, dash3 + 1, dash4) & 0xffffL;
|
||||||
leastSigBits <<= 48;
|
leastSigBits <<= 48;
|
||||||
leastSigBits |= Long.decode(components[4]).longValue();
|
leastSigBits |= Long.parseLong(name, 16, dash4 + 1) & 0xffffffffffffL;
|
||||||
|
|
||||||
return new UUID(mostSigBits, leastSigBits);
|
return new UUID(mostSigBits, leastSigBits);
|
||||||
}
|
}
|
||||||
@ -373,17 +392,17 @@ public final class UUID implements java.io.Serializable, Comparable<UUID> {
|
|||||||
* @return A string representation of this {@code UUID}
|
* @return A string representation of this {@code UUID}
|
||||||
*/
|
*/
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return (digits(mostSigBits >> 32, 8) + "-" +
|
char[] chars = new char[36];
|
||||||
digits(mostSigBits >> 16, 4) + "-" +
|
jla.formatUnsignedLong(mostSigBits >> 32, 4, chars, 0, 8);
|
||||||
digits(mostSigBits, 4) + "-" +
|
chars[8] = '-';
|
||||||
digits(leastSigBits >> 48, 4) + "-" +
|
jla.formatUnsignedLong(mostSigBits >> 16, 4, chars, 9, 4);
|
||||||
digits(leastSigBits, 12));
|
chars[13] = '-';
|
||||||
}
|
jla.formatUnsignedLong(mostSigBits, 4, chars, 14, 4);
|
||||||
|
chars[18] = '-';
|
||||||
/** Returns val represented by the specified number of hex digits. */
|
jla.formatUnsignedLong(leastSigBits >> 48, 4, chars, 19, 4);
|
||||||
private static String digits(long val, int digits) {
|
chars[23] = '-';
|
||||||
long hi = 1L << (digits * 4);
|
jla.formatUnsignedLong(leastSigBits, 4, chars, 24, 12);
|
||||||
return Long.toHexString(hi | (val & (hi - 1))).substring(1);
|
return jla.newStringUnsafe(chars);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,6 +96,23 @@ public class UUIDTest {
|
|||||||
if (!u1.equals(u2))
|
if (!u1.equals(u2))
|
||||||
throw new Exception("UUID -> string -> UUID failed");
|
throw new Exception("UUID -> string -> UUID failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testFromStringError("-0");
|
||||||
|
testFromStringError("x");
|
||||||
|
testFromStringError("----");
|
||||||
|
testFromStringError("-0-0-0-0");
|
||||||
|
testFromStringError("0-0-0-0-");
|
||||||
|
testFromStringError("0-0-0-0-0-");
|
||||||
|
testFromStringError("0-0-0-0-x");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testFromStringError(String str) {
|
||||||
|
try {
|
||||||
|
UUID test = UUID.fromString(str);
|
||||||
|
throw new RuntimeException("Should have thrown IAE");
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void versionTest() throws Exception {
|
private static void versionTest() throws Exception {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user