From 5a5bd474934833408b489dee4926a311e8d4a7e0 Mon Sep 17 00:00:00 2001 From: benoit Date: Tue, 28 Nov 2017 13:50:03 +0100 Subject: [PATCH] HHH-12131 Avoid allocating unneeded byte array when parsing or transforming UUID. --- .../hibernate/internal/util/BytesHelper.java | 46 ++++++++++++++---- .../descriptor/java/UUIDTypeDescriptor.java | 11 ++--- .../hibernate/test/util/BytesHelperTest.java | 47 +++++++++++++++++++ 3 files changed, 87 insertions(+), 17 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/util/BytesHelperTest.java diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/BytesHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/BytesHelper.java index 4d7a779726..a822200afb 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/BytesHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/BytesHelper.java @@ -68,16 +68,29 @@ public final class BytesHelper { */ public static byte[] fromLong(long longValue) { byte[] bytes = new byte[8]; - bytes[0] = (byte) ( longValue >> 56 ); - bytes[1] = (byte) ( ( longValue << 8 ) >> 56 ); - bytes[2] = (byte) ( ( longValue << 16 ) >> 56 ); - bytes[3] = (byte) ( ( longValue << 24 ) >> 56 ); - bytes[4] = (byte) ( ( longValue << 32 ) >> 56 ); - bytes[5] = (byte) ( ( longValue << 40 ) >> 56 ); - bytes[6] = (byte) ( ( longValue << 48 ) >> 56 ); - bytes[7] = (byte) ( ( longValue << 56 ) >> 56 ); + fromLong(longValue, bytes, 0); return bytes; } + + /** + * Interpret a long as its binary form + * + * @param longValue The long to interpret to binary + * @param dest the destination array. + * @param destPos starting position in the destination array. + * @return The binary + */ + public static void fromLong(long longValue, byte[] dest, int destPos) { + + dest[destPos] = (byte) ( longValue >> 56 ); + dest[destPos + 1] = (byte) ( ( longValue << 8 ) >> 56 ); + dest[destPos + 2] = (byte) ( ( longValue << 16 ) >> 56 ); + dest[destPos + 3] = (byte) ( ( longValue << 24 ) >> 56 ); + dest[destPos + 4] = (byte) ( ( longValue << 32 ) >> 56 ); + dest[destPos + 5] = (byte) ( ( longValue << 40 ) >> 56 ); + dest[destPos + 6] = (byte) ( ( longValue << 48 ) >> 56 ); + dest[destPos + 7] = (byte) ( ( longValue << 56 ) >> 56 ); + } /** * Interpret the binary representation of a long. @@ -87,14 +100,27 @@ public final class BytesHelper { * @return The long */ public static long asLong(byte[] bytes) { + return asLong(bytes, 0); + } + + /** + * Interpret the binary representation of a long. + * + * @param bytes The bytes to interpret. + * @param srcPos starting position in the source array. + * + * @return The long + */ + public static long asLong(byte[] bytes, int srcPos) { if ( bytes == null ) { return 0; } - if ( bytes.length != 8 ) { + final int size = srcPos + 8; + if ( bytes.length < size ) { throw new IllegalArgumentException( "Expecting 8 byte values to construct a long" ); } long value = 0; - for (int i=0; i<8; i++) { + for (int i=srcPos; i { public byte[] transform(UUID uuid) { byte[] bytes = new byte[16]; - System.arraycopy( BytesHelper.fromLong( uuid.getMostSignificantBits() ), 0, bytes, 0, 8 ); - System.arraycopy( BytesHelper.fromLong( uuid.getLeastSignificantBits() ), 0, bytes, 8, 8 ); + BytesHelper.fromLong( uuid.getMostSignificantBits(), bytes, 0); + BytesHelper.fromLong( uuid.getLeastSignificantBits(), bytes, 8 ); return bytes; } public UUID parse(Object value) { - byte[] msb = new byte[8]; - byte[] lsb = new byte[8]; - System.arraycopy( value, 0, msb, 0, 8 ); - System.arraycopy( value, 8, lsb, 0, 8 ); - return new UUID( BytesHelper.asLong( msb ), BytesHelper.asLong( lsb ) ); + byte[] bytea = (byte[]) value; + return new UUID( BytesHelper.asLong( bytea, 0 ), BytesHelper.asLong( bytea, 8 ) ); } } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/util/BytesHelperTest.java b/hibernate-core/src/test/java/org/hibernate/test/util/BytesHelperTest.java new file mode 100644 index 0000000000..4722edcd8a --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/util/BytesHelperTest.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.util; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import org.hibernate.internal.util.BytesHelper; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +/** + * @author Benoit W + */ +public class BytesHelperTest extends BaseUnitTestCase { + + @Test + public void testAsLongNullArray() { + assertEquals(0, BytesHelper.asLong(null, 0)); + } + + @Test(expected=IllegalArgumentException.class) + public void testAsLongArrayTooSmall() { + byte[] src = new byte[16]; + assertEquals(0, BytesHelper.asLong(src, 9)); + } + + @Test + public void testAsLong() { + byte[] src = new byte[] {-92, -120, -59, -64, 97, 55, -41, -55, 64, -43, 20, 109, -7, -95, 77, -115}; + assertEquals(-6590800624601278519L, BytesHelper.asLong(src, 0)); + assertEquals(4671662651038846349L, BytesHelper.asLong(src, 8)); + } + + @Test + public void testfromLong() { + byte[] expected = new byte[] {-92, -120, -59, -64, 97, 55, -41, -55, 64, -43, 20, 109, -7, -95, 77, -115}; + byte[] dest = new byte[16]; + BytesHelper.fromLong(-6590800624601278519L, dest, 0); + BytesHelper.fromLong(4671662651038846349L, dest, 8); + assertArrayEquals(expected, dest); + } +}