OpenJDK / jdk9 / jdk9 / jdk
changeset 10370:3b298c230549
8006627: UUID to/from String performance should be improved by reducing object allocations
Reviewed-by: mduigou, plevart
Contributed-by: Steven Schlansker <stevenschlansker@gmail.com>, Claes Redestad <claes.redestad@oracle.com>
author | redestad |
---|---|
date | Mon, 21 Jul 2014 23:07:40 +0200 |
parents | a602ef090ee9 |
children | 87fac66a55b4 |
files | src/share/classes/java/util/UUID.java test/java/util/UUID/UUIDTest.java |
diffstat | 2 files changed, 58 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/java/util/UUID.java Tue Jul 22 13:13:27 2014 -0700 +++ b/src/share/classes/java/util/UUID.java Mon Jul 21 23:07:40 2014 +0200 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,9 @@ import java.security.*; +import sun.misc.JavaLangAccess; +import sun.misc.SharedSecrets; + /** * A class that represents an immutable universally unique identifier (UUID). * A UUID represents a 128-bit value. @@ -88,6 +91,8 @@ */ private final long leastSigBits; + private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); + /* * The random number generator used by this class to create random * based UUIDs. In a holder class to defer initialization until needed. @@ -189,21 +194,35 @@ * */ public static UUID fromString(String name) { - String[] components = name.split("-"); - if (components.length != 5) - throw new IllegalArgumentException("Invalid UUID string: "+name); - for (int i=0; i<5; i++) - components[i] = "0x"+components[i]; + if (name.length() > 36) { + 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); - long mostSigBits = Long.decode(components[0]).longValue(); + // 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); + } + + long mostSigBits = Long.parseLong(name, 16, 0, dash1) & 0xffffffffL; mostSigBits <<= 16; - mostSigBits |= Long.decode(components[1]).longValue(); + mostSigBits |= Long.parseLong(name, 16, dash1 + 1, dash2) & 0xffffL; 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 |= Long.decode(components[4]).longValue(); + leastSigBits |= Long.parseLong(name, 16, dash4 + 1) & 0xffffffffffffL; return new UUID(mostSigBits, leastSigBits); } @@ -373,17 +392,17 @@ * @return A string representation of this {@code UUID} */ public String toString() { - return (digits(mostSigBits >> 32, 8) + "-" + - digits(mostSigBits >> 16, 4) + "-" + - digits(mostSigBits, 4) + "-" + - digits(leastSigBits >> 48, 4) + "-" + - digits(leastSigBits, 12)); - } - - /** Returns val represented by the specified number of hex digits. */ - private static String digits(long val, int digits) { - long hi = 1L << (digits * 4); - return Long.toHexString(hi | (val & (hi - 1))).substring(1); + char[] chars = new char[36]; + jla.formatUnsignedLong(mostSigBits >> 32, 4, chars, 0, 8); + chars[8] = '-'; + jla.formatUnsignedLong(mostSigBits >> 16, 4, chars, 9, 4); + chars[13] = '-'; + jla.formatUnsignedLong(mostSigBits, 4, chars, 14, 4); + chars[18] = '-'; + jla.formatUnsignedLong(leastSigBits >> 48, 4, chars, 19, 4); + chars[23] = '-'; + jla.formatUnsignedLong(leastSigBits, 4, chars, 24, 12); + return jla.newStringUnsafe(chars); } /**
--- a/test/java/util/UUID/UUIDTest.java Tue Jul 22 13:13:27 2014 -0700 +++ b/test/java/util/UUID/UUIDTest.java Mon Jul 21 23:07:40 2014 +0200 @@ -96,6 +96,23 @@ if (!u1.equals(u2)) 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 {