HBASE-21208 Bytes#toShort doesn't work without unsafe

Signed-off-by: Ted Yu <yuzhihong@gmail.com>
Signed-off-by: anoopsamjohn <anoopsamjohn@gmail.com>
Signed-off-by: Reid Chan <reidchan@apache.org>

Conflicts:
	hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java
	hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestBytes.java

Amending-Author: Andrew Purtell <apurtell@apache.org>
This commit is contained in:
Chia-Ping Tsai 2018-09-25 10:18:47 +08:00 committed by Andrew Purtell
parent 21cfff857d
commit 2f541f5710
No known key found for this signature in database
GPG Key ID: 8597754DD5365CCD
2 changed files with 56 additions and 2 deletions

View File

@ -129,7 +129,8 @@ public class Bytes implements Comparable<Bytes> {
// SizeOf which uses java.lang.instrument says 24 bytes. (3 longs?)
public static final int ESTIMATED_HEAP_TAX = 16;
private static final boolean UNSAFE_UNALIGNED = UnsafeAvailChecker.unaligned();
@VisibleForTesting
static final boolean UNSAFE_UNALIGNED = UnsafeAvailChecker.unaligned();
/**
* Returns length of the byte array, returning 0 if the array is null.
@ -1082,7 +1083,15 @@ public class Bytes implements Comparable<Bytes> {
if (length != SIZEOF_SHORT || offset + length > bytes.length) {
throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_SHORT);
}
return ConverterHolder.BEST_CONVERTER.toShort(bytes, offset, length);
if (UNSAFE_UNALIGNED) {
return ConverterHolder.BEST_CONVERTER.toShort(bytes, offset, length);
} else {
short n = 0;
n = (short) (n ^ (bytes[offset] & 0xFF));
n = (short) (n << 8);
n = (short) (n ^ (bytes[offset + 1] & 0xFF));
return n;
}
}
/**

View File

@ -22,6 +22,8 @@ import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@ -39,6 +41,49 @@ import org.junit.experimental.categories.Category;
@Category(SmallTests.class)
public class TestBytes extends TestCase {
private static void setUnsafe(boolean value) throws Exception {
Field field = Bytes.class.getDeclaredField("UNSAFE_UNALIGNED");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
int oldModifiers = field.getModifiers();
modifiersField.setInt(field, oldModifiers & ~Modifier.FINAL);
try {
field.set(null, value);
} finally {
modifiersField.setInt(field, oldModifiers);
}
assertEquals(Bytes.UNSAFE_UNALIGNED, value);
}
public void testShort() throws Exception {
testShort(false);
}
public void testShortUnsafe() throws Exception {
testShort(true);
}
private static void testShort(boolean unsafe) throws Exception {
setUnsafe(unsafe);
try {
for (short n : Arrays.asList(
Short.MIN_VALUE,
(short) -100,
(short) -1,
(short) 0,
(short) 1,
(short) 300,
Short.MAX_VALUE)) {
byte[] bytes = Bytes.toBytes(n);
assertEquals(Bytes.toShort(bytes, 0, bytes.length), n);
}
} finally {
setUnsafe(UnsafeAvailChecker.unaligned());
}
}
public void testNullHashCode() {
byte [] b = null;
Exception ee = null;