diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java index 0f01fb7..500d01d 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java @@ -35,6 +35,7 @@ import org.apache.hadoop.hbase.util.ByteStringer; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Pair; import org.apache.hadoop.hbase.util.UnsafeAccess; +import org.apache.hadoop.hbase.util.UnsafeAvailChecker; import com.google.common.annotations.VisibleForTesting; import com.google.protobuf.InvalidProtocolBufferException; @@ -60,6 +61,7 @@ import com.google.protobuf.InvalidProtocolBufferException; @InterfaceAudience.Public @InterfaceStability.Evolving public class FuzzyRowFilter extends FilterBase { + private static final boolean UNSAFE_UNALIGNED = UnsafeAvailChecker.unaligned(); private List> fuzzyKeysData; private boolean done = false; @@ -94,7 +96,7 @@ public class FuzzyRowFilter extends FilterBase { } private void preprocessSearchKey(Pair p) { - if (UnsafeAccess.unaligned() == false) { + if (!UNSAFE_UNALIGNED) { // do nothing return; } @@ -113,7 +115,7 @@ public class FuzzyRowFilter extends FilterBase { * @return mask array */ private byte[] preprocessMask(byte[] mask) { - if (UnsafeAccess.unaligned() == false) { + if (!UNSAFE_UNALIGNED) { // do nothing return mask; } @@ -318,7 +320,7 @@ public class FuzzyRowFilter extends FilterBase { static SatisfiesCode satisfies(boolean reverse, byte[] row, int offset, int length, byte[] fuzzyKeyBytes, byte[] fuzzyKeyMeta) { - if (UnsafeAccess.unaligned() == false) { + if (!UNSAFE_UNALIGNED) { return satisfiesNoUnsafe(reverse, row, offset, length, fuzzyKeyBytes, fuzzyKeyMeta); } diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/nio/SingleByteBuff.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/nio/SingleByteBuff.java index 227216a..946962b 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/nio/SingleByteBuff.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/nio/SingleByteBuff.java @@ -23,6 +23,7 @@ import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.util.ByteBufferUtils; import org.apache.hadoop.hbase.util.ObjectIntPair; import org.apache.hadoop.hbase.util.UnsafeAccess; +import org.apache.hadoop.hbase.util.UnsafeAvailChecker; import sun.nio.ch.DirectBuffer; @@ -33,8 +34,8 @@ import sun.nio.ch.DirectBuffer; @InterfaceAudience.Private public class SingleByteBuff extends ByteBuff { - private static final boolean UNSAFE_AVAIL = UnsafeAccess.isAvailable(); - private static final boolean UNSAFE_UNALIGNED = UnsafeAccess.unaligned(); + private static final boolean UNSAFE_AVAIL = UnsafeAvailChecker.isAvailable(); + private static final boolean UNSAFE_UNALIGNED = UnsafeAvailChecker.unaligned(); // Underlying BB private final ByteBuffer buf; diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/ByteBufferUtils.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/ByteBufferUtils.java index 7f3d777..6ca97da 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/ByteBufferUtils.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/ByteBufferUtils.java @@ -47,8 +47,8 @@ public final class ByteBufferUtils { public final static int VALUE_MASK = 0x7f; public final static int NEXT_BIT_SHIFT = 7; public final static int NEXT_BIT_MASK = 1 << 7; - private static final boolean UNSAFE_AVAIL = UnsafeAccess.isAvailable(); - private static final boolean UNSAFE_UNALIGNED = UnsafeAccess.unaligned(); + private static final boolean UNSAFE_AVAIL = UnsafeAvailChecker.isAvailable(); + private static final boolean UNSAFE_UNALIGNED = UnsafeAvailChecker.unaligned(); private ByteBufferUtils() { } @@ -150,7 +150,7 @@ public final class ByteBufferUtils { } public static byte toByte(ByteBuffer buffer, int offset) { - if (UnsafeAccess.isAvailable()) { + if (UNSAFE_AVAIL) { return UnsafeAccess.toByte(buffer, offset); } else { return buffer.get(offset); @@ -202,7 +202,7 @@ public final class ByteBufferUtils { } public static int putByte(ByteBuffer buffer, int offset, byte b) { - if (UnsafeAccess.isAvailable()) { + if (UNSAFE_AVAIL) { return UnsafeAccess.putByte(buffer, offset, b); } else { buffer.put(offset, b); @@ -369,7 +369,7 @@ public final class ByteBufferUtils { * @param out destination buffer */ public static void copyFromBufferToBuffer(ByteBuffer in, ByteBuffer out) { - if (UnsafeAccess.isAvailable()) { + if (UNSAFE_AVAIL) { int length = in.remaining(); UnsafeAccess.copy(in, in.position(), out, out.position(), length); out.position(out.position() + length); diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java index 987f1e2..aae6c4c 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java @@ -132,6 +132,7 @@ public class Bytes implements Comparable { // 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(); /** * Returns length of the byte array, returning 0 if the array is null. @@ -789,7 +790,7 @@ public class Bytes implements Comparable { if (length != SIZEOF_LONG || offset + length > bytes.length) { throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_LONG); } - if (UnsafeAccess.unaligned()) { + if (UNSAFE_UNALIGNED) { return UnsafeAccess.toLong(bytes, offset); } else { long l = 0; @@ -830,7 +831,7 @@ public class Bytes implements Comparable { throw new IllegalArgumentException("Not enough room to put a long at" + " offset " + offset + " in a " + bytes.length + " byte array"); } - if (UnsafeAccess.unaligned()) { + if (UNSAFE_UNALIGNED) { return UnsafeAccess.putLong(bytes, offset, val); } else { for(int i = offset + 7; i > offset; i--) { @@ -981,7 +982,7 @@ public class Bytes implements Comparable { if (length != SIZEOF_INT || offset + length > bytes.length) { throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_INT); } - if (UnsafeAccess.unaligned()) { + if (UNSAFE_UNALIGNED) { return UnsafeAccess.toInt(bytes, offset); } else { int n = 0; @@ -1065,7 +1066,7 @@ public class Bytes implements Comparable { throw new IllegalArgumentException("Not enough room to put an int at" + " offset " + offset + " in a " + bytes.length + " byte array"); } - if (UnsafeAccess.unaligned()) { + if (UNSAFE_UNALIGNED) { return UnsafeAccess.putInt(bytes, offset, val); } else { for(int i= offset + 3; i > offset; i--) { @@ -1135,7 +1136,7 @@ public class Bytes implements Comparable { if (length != SIZEOF_SHORT || offset + length > bytes.length) { throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_SHORT); } - if (UnsafeAccess.unaligned()) { + if (UNSAFE_UNALIGNED) { return UnsafeAccess.toShort(bytes, offset); } else { short n = 0; @@ -1173,7 +1174,7 @@ public class Bytes implements Comparable { throw new IllegalArgumentException("Not enough room to put a short at" + " offset " + offset + " in a " + bytes.length + " byte array"); } - if (UnsafeAccess.unaligned()) { + if (UNSAFE_UNALIGNED) { return UnsafeAccess.putShort(bytes, offset, val); } else { bytes[offset+1] = (byte) val; @@ -1477,7 +1478,7 @@ public class Bytes implements Comparable { static final Unsafe theUnsafe; static { - if (UnsafeAccess.unaligned()) { + if (UNSAFE_UNALIGNED) { theUnsafe = UnsafeAccess.theUnsafe; } else { // It doesn't matter what we throw; diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAccess.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAccess.java index af2632b..9078def 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAccess.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAccess.java @@ -18,7 +18,6 @@ package org.apache.hadoop.hbase.util; import java.lang.reflect.Field; -import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.security.AccessController; @@ -34,14 +33,11 @@ import sun.nio.ch.DirectBuffer; @InterfaceAudience.Private @InterfaceStability.Evolving -@edu.umd.cs.findbugs.annotations.SuppressWarnings(value="REC_CATCH_EXCEPTION", - justification="If exception, presume unaligned") public final class UnsafeAccess { private static final Log LOG = LogFactory.getLog(UnsafeAccess.class); static final Unsafe theUnsafe; - private static boolean unaligned; /** The offset to the first element in a byte array. */ public static final long BYTE_ARRAY_BASE_OFFSET; @@ -70,38 +66,13 @@ public final class UnsafeAccess { if (theUnsafe != null) { BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class); - try { - // Using java.nio.Bits#unaligned() to check for unaligned-access capability - Class clazz = Class.forName("java.nio.Bits"); - Method m = clazz.getDeclaredMethod("unaligned"); - m.setAccessible(true); - unaligned = (boolean) m.invoke(null); - } catch (Exception e) { - unaligned = false; // FindBugs: Causes REC_CATCH_EXCEPTION. Suppressed. - } } else{ BYTE_ARRAY_BASE_OFFSET = -1; - unaligned = false; } } private UnsafeAccess(){} - /** - * @return true when running JVM is having sun's Unsafe package available in it. - */ - public static boolean isAvailable() { - return theUnsafe != null; - } - - /** - * @return true when running JVM is having sun's Unsafe package available in it and underlying - * system having unaligned-access capability. - */ - public static boolean unaligned() { - return unaligned; - } - // APIs to read primitive data from a byte[] using Unsafe way /** * Converts a byte array to a short value considering it was written in big-endian format. diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAvailChecker.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAvailChecker.java new file mode 100644 index 0000000..8c22947 --- /dev/null +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAvailChecker.java @@ -0,0 +1,86 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase.util; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.hbase.classification.InterfaceAudience; + +@InterfaceAudience.Private +public class UnsafeAvailChecker { + + private static final String CLASS_NAME = "sun.misc.Unsafe"; + private static final Log LOG = LogFactory.getLog(UnsafeAvailChecker.class); + private static boolean avail = false; + private static boolean unaligned = false; + + static { + avail = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Boolean run() { + try { + Class clazz = Class.forName(CLASS_NAME); + Field f = clazz.getDeclaredField("theUnsafe"); + f.setAccessible(true); + return f.get(null) != null; + } catch (Throwable e) { + LOG.warn("sun.misc.Unsafe is not available/accessible", e); + } + return false; + } + }); + // When Unsafe itself is not available/accessible consider unaligned as false. + if (avail) { + try { + // Using java.nio.Bits#unaligned() to check for unaligned-access capability + Class clazz = Class.forName("java.nio.Bits"); + Method m = clazz.getDeclaredMethod("unaligned"); + m.setAccessible(true); + unaligned = (boolean) m.invoke(null); + } catch (Exception e) { + LOG.warn("java.nio.Bits#unaligned() check failed." + + "Unsafe based read/write of primitive types won't be used", e); + } + } + } + + /** + * @return true when running JVM is having sun's Unsafe package available in it and it is + * accessible. + */ + public static boolean isAvailable() { + return avail; + } + + /** + * @return true when running JVM is having sun's Unsafe package available in it and underlying + * system having unaligned-access capability. + */ + public static boolean unaligned() { + return unaligned; + } + + private UnsafeAvailChecker() { + // private constructor to avoid instantiation + } +} \ No newline at end of file