HHH-12131 Avoid allocating unneeded byte array when parsing or

transforming UUID.
This commit is contained in:
benoit 2017-11-28 13:50:03 +01:00 committed by Steve Ebersole
parent 4efac1369a
commit 5a5bd47493
3 changed files with 87 additions and 17 deletions

View File

@ -68,17 +68,30 @@ 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<size; i++) {
value = (value << 8) | (bytes[i] & 0xff);
}
return value;

View File

@ -99,17 +99,14 @@ public class UUIDTypeDescriptor extends AbstractTypeDescriptor<UUID> {
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 ) );
}
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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);
}
}