This is an automated email from the ASF dual-hosted git repository.
zhangduo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hbase-thirdparty.git
The following commit(s) were added to refs/heads/master by this push:
new 9f5c6e2 HBASE-26773 [hbase-thirdparty] Introduce a hbase-unsafe
module in hbase-thirdparty to remove the direct references of Unsafe in our
main code base (#78)
9f5c6e2 is described below
commit 9f5c6e27c0519c0afb23e3dfcac5ddd19bffcfa9
Author: Duo Zhang <[email protected]>
AuthorDate: Tue Mar 1 20:58:22 2022 +0800
HBASE-26773 [hbase-thirdparty] Introduce a hbase-unsafe module in
hbase-thirdparty to remove the direct references of Unsafe in our main code
base (#78)
Signed-off-by: Andrew Purtell <[email protected]>
---
hbase-unsafe/pom.xml | 92 ++++
.../apache/hadoop/hbase/unsafe/HBaseUnsafe.java | 562 +++++++++++++++++++++
.../hadoop/hbase/unsafe/HBaseUnsafeInternal.java | 414 +++++++++++++++
.../hadoop/hbase/unsafe/TestHBaseUnsafe.java | 35 ++
pom.xml | 5 +
5 files changed, 1108 insertions(+)
diff --git a/hbase-unsafe/pom.xml b/hbase-unsafe/pom.xml
new file mode 100644
index 0000000..555b54f
--- /dev/null
+++ b/hbase-unsafe/pom.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+ <!--
+/**
+ * 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.
+ */
+
+-->
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.hbase.thirdparty</groupId>
+ <artifactId>hbase-thirdparty</artifactId>
+ <version>4.0.2-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <artifactId>hbase-unsafe</artifactId>
+ <name>Apache HBase Unsafe Wrapper</name>
+ <description>
+ Wrap sun.misc.Unsafe to avoid referencing it in the main code base
+ </description>
+ <properties>
+
<maven.test.redirectTestOutputToFile>true</maven.test.redirectTestOutputToFile>
+ <!-- This library is meant to work with whatever HBase and Hadoop combos
we still list
+ as recommended. The version here is what we'll test out of the box if
you run mvn test
+ -->
+ <hbase.stable.version>2.4.8</hbase.stable.version>
+ <!-- should match the slf4j-api version used in the above hbase -->
+ <slf4j.version>1.7.30</slf4j.version>
+ <!-- These maybe need to match the main repo -->
+ <maven.checkstyle.version>3.1.0</maven.checkstyle.version>
+ <checkstyle.version>8.28</checkstyle.version>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.13.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>${slf4j.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>${maven.checkstyle.version}</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.hbase</groupId>
+ <artifactId>hbase-checkstyle</artifactId>
+ <version>${hbase.stable.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.puppycrawl.tools</groupId>
+ <artifactId>checkstyle</artifactId>
+ <version>${checkstyle.version}</version>
+ </dependency>
+ </dependencies>
+ <configuration>
+ <configLocation>hbase/checkstyle.xml</configLocation>
+
<suppressionsLocation>hbase/checkstyle-suppressions.xml</suppressionsLocation>
+ <includeTestSourceDirectory>true</includeTestSourceDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git
a/hbase-unsafe/src/main/java/org/apache/hadoop/hbase/unsafe/HBaseUnsafe.java
b/hbase-unsafe/src/main/java/org/apache/hadoop/hbase/unsafe/HBaseUnsafe.java
new file mode 100644
index 0000000..aa142b9
--- /dev/null
+++ b/hbase-unsafe/src/main/java/org/apache/hadoop/hbase/unsafe/HBaseUnsafe.java
@@ -0,0 +1,562 @@
+/**
+ * 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.unsafe;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Delegate all methods of {@link HBaseUnsafeInternal}, so we will not touch
the actual
+ * {@code sun.misc.Unsafe} class until we actually call the methods.
+ */
+public final class HBaseUnsafe {
+
+ private static final String CLASS_NAME = "sun.misc.Unsafe";
+ private static final Logger LOG = LoggerFactory.getLogger(HBaseUnsafe.class);
+ private static final boolean AVAIL;
+ private static final boolean UNALIGNED;
+
+ static {
+ AVAIL = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+
+ @Override
+ public Boolean run() {
+ return checkAvailable();
+ }
+ });
+ UNALIGNED = checkUnaligned();
+ }
+
+ private static boolean checkAvailable() {
+ try {
+ Class<?> clazz = Class.forName(CLASS_NAME);
+ Field f = clazz.getDeclaredField("theUnsafe");
+ f.setAccessible(true);
+ Object theUnsafe = f.get(null);
+ if (theUnsafe == null) {
+ LOG.warn("Could not get static instance from sun.misc.Unsafe");
+ return false;
+ }
+ // Check for availability of all methods used by UnsafeAccess
+ Method m;
+ try {
+ m = clazz.getDeclaredMethod("arrayBaseOffset", Class.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing arrayBaseOffset(Class)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("copyMemory", Object.class, long.class,
Object.class,
+ long.class, long.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing
copyMemory(Object,long,Object,long,long)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("getByte", Object.class, long.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing getByte(Object,long)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("getShort", long.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing getShort(long)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("getShort", Object.class, long.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing getShort(Object,long)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("getInt", long.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing getInt(long)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("getInt", Object.class, long.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing getInt(Object,long)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("getLong", long.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing getLong(long)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("getLong", Object.class, long.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing getLong(Object,long)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("putByte", long.class, byte.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing putByte(long,byte)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("putByte", Object.class, long.class,
byte.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing putByte(Object,long,byte)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("putShort", long.class, short.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing putShort(long,short)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("putShort", Object.class, long.class,
short.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing putShort(Object,long,short)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("putInt", long.class, int.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing putInt(long,int)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("putInt", Object.class, long.class,
int.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing putInt(Object,long,int)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("putLong", long.class, long.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing putLong(long,long)");
+ return false;
+ }
+ m = clazz.getDeclaredMethod("putLong", Object.class, long.class,
long.class);
+ if (m == null) {
+ LOG.warn("sun.misc.Unsafe is missing putLong(Object,long,long)");
+ return false;
+ }
+ // theUnsafe is accessible and all methods are available
+ return true;
+ } catch (Throwable e) {
+ LOG.warn("sun.misc.Unsafe is missing one or more required methods", e);
+ }
+ } catch (Throwable e) {
+ LOG.warn("sun.misc.Unsafe is not available/accessible", e);
+ }
+ return false;
+ }
+
+ private static boolean checkUnaligned() {
+ // When Unsafe itself is not available/accessible consider unaligned as
false.
+ if (!AVAIL) {
+ return false;
+ }
+ String arch = System.getProperty("os.arch");
+ if ("ppc64".equals(arch) || "ppc64le".equals(arch) ||
"aarch64".equals(arch)) {
+ // java.nio.Bits.unaligned() wrongly returns false on ppc (JDK-8165231),
+ return true;
+ }
+ 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);
+ return (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 false;
+ }
+
+ /**
+ * @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 HBaseUnsafe() {
+ // private constructor to avoid instantiation
+ }
+
+ public static int getInt(Object o, long offset) {
+ return HBaseUnsafeInternal.getInt(o, offset);
+ }
+
+ public static void putInt(Object o, long offset, int x) {
+ HBaseUnsafeInternal.putInt(o, offset, x);
+ }
+
+ public static Object getObject(Object o, long offset) {
+ return HBaseUnsafeInternal.getObject(o, offset);
+ }
+
+ public static void putObject(Object o, long offset, Object x) {
+ HBaseUnsafeInternal.putObject(o, offset, x);
+ }
+
+ public static boolean getBoolean(Object o, long offset) {
+ return HBaseUnsafeInternal.getBoolean(o, offset);
+ }
+
+ public static void putBoolean(Object o, long offset, boolean x) {
+ HBaseUnsafeInternal.putBoolean(o, offset, x);
+ }
+
+ public static byte getByte(Object o, long offset) {
+ return HBaseUnsafeInternal.getByte(o, offset);
+ }
+
+ public static void putByte(Object o, long offset, byte x) {
+ HBaseUnsafeInternal.putByte(o, offset, x);
+ }
+
+ public static short getShort(Object o, long offset) {
+ return HBaseUnsafeInternal.getShort(o, offset);
+ }
+
+ public static void putShort(Object o, long offset, short x) {
+ HBaseUnsafeInternal.putShort(o, offset, x);
+ }
+
+ public static char getChar(Object o, long offset) {
+ return HBaseUnsafeInternal.getChar(o, offset);
+ }
+
+ public static void putChar(Object o, long offset, char x) {
+ HBaseUnsafeInternal.putChar(o, offset, x);
+ }
+
+ public static long getLong(Object o, long offset) {
+ return HBaseUnsafeInternal.getLong(o, offset);
+ }
+
+ public static void putLong(Object o, long offset, long x) {
+ HBaseUnsafeInternal.putLong(o, offset, x);
+ }
+
+ public static float getFloat(Object o, long offset) {
+ return HBaseUnsafeInternal.getFloat(o, offset);
+ }
+
+ public static void putFloat(Object o, long offset, float x) {
+ HBaseUnsafeInternal.putFloat(o, offset, x);
+ }
+
+ public static double getDouble(Object o, long offset) {
+ return HBaseUnsafeInternal.getDouble(o, offset);
+ }
+
+ public static void putDouble(Object o, long offset, double x) {
+ HBaseUnsafeInternal.putDouble(o, offset, x);
+ }
+
+ public static byte getByte(long address) {
+ return HBaseUnsafeInternal.getByte(address);
+ }
+
+ public static void putByte(long address, byte x) {
+ HBaseUnsafeInternal.putByte(address, x);
+ }
+
+ public static short getShort(long address) {
+ return HBaseUnsafeInternal.getShort(address);
+ }
+
+ public static void putShort(long address, short x) {
+ HBaseUnsafeInternal.putShort(address, x);
+ }
+
+ public static char getChar(long address) {
+ return HBaseUnsafeInternal.getChar(address);
+ }
+
+ public static void putChar(long address, char x) {
+ HBaseUnsafeInternal.putChar(address, x);
+ }
+
+ public static int getInt(long address) {
+ return HBaseUnsafeInternal.getInt(address);
+ }
+
+ public static void putInt(long address, int x) {
+ HBaseUnsafeInternal.putInt(address, x);
+ }
+
+ public static long getLong(long address) {
+ return HBaseUnsafeInternal.getLong(address);
+ }
+
+ public static void putLong(long address, long x) {
+ HBaseUnsafeInternal.putLong(address, x);
+ }
+
+ public static float getFloat(long address) {
+ return HBaseUnsafeInternal.getFloat(address);
+ }
+
+ public static void putFloat(long address, float x) {
+ HBaseUnsafeInternal.putFloat(address, x);
+ }
+
+ public static double getDouble(long address) {
+ return HBaseUnsafeInternal.getDouble(address);
+ }
+
+ public static void putDouble(long address, double x) {
+ HBaseUnsafeInternal.putDouble(address, x);
+ }
+
+ public static long getAddress(long address) {
+ return HBaseUnsafeInternal.getAddress(address);
+ }
+
+ public static void putAddress(long address, long x) {
+ HBaseUnsafeInternal.putAddress(address, x);
+ }
+
+ public static long allocateMemory(long bytes) {
+ return HBaseUnsafeInternal.allocateMemory(bytes);
+ }
+
+ public static long reallocateMemory(long address, long bytes) {
+ return HBaseUnsafeInternal.reallocateMemory(address, bytes);
+ }
+
+ public static void setMemory(Object o, long offset, long bytes, byte value) {
+ HBaseUnsafeInternal.setMemory(o, offset, bytes, value);
+ }
+
+ public static void setMemory(long address, long bytes, byte value) {
+ HBaseUnsafeInternal.setMemory(address, bytes, value);
+ }
+
+ public static void copyMemory(Object srcBase, long srcOffset, Object
destBase, long destOffset,
+ long bytes) {
+ HBaseUnsafeInternal.copyMemory(srcBase, srcOffset, destBase, destOffset,
bytes);
+ }
+
+ public static void copyMemory(long srcAddress, long destAddress, long bytes)
{
+ HBaseUnsafeInternal.copyMemory(srcAddress, destAddress, bytes);
+ }
+
+ public static void freeMemory(long address) {
+ HBaseUnsafeInternal.freeMemory(address);
+ }
+
+ public static long staticFieldOffset(Field f) {
+ return HBaseUnsafeInternal.staticFieldOffset(f);
+ }
+
+ public static long objectFieldOffset(Field f) {
+ return HBaseUnsafeInternal.objectFieldOffset(f);
+ }
+
+ public static Object staticFieldBase(Field f) {
+ return HBaseUnsafeInternal.staticFieldBase(f);
+ }
+
+ public static boolean shouldBeInitialized(Class<?> c) {
+ return HBaseUnsafeInternal.shouldBeInitialized(c);
+ }
+
+ public static void ensureClassInitialized(Class<?> c) {
+ HBaseUnsafeInternal.ensureClassInitialized(c);
+ }
+
+ public static int arrayBaseOffset(Class<?> arrayClass) {
+ return HBaseUnsafeInternal.arrayBaseOffset(arrayClass);
+ }
+
+ public static int arrayIndexScale(Class<?> arrayClass) {
+ return HBaseUnsafeInternal.arrayIndexScale(arrayClass);
+ }
+
+ public static int addressSize() {
+ return HBaseUnsafeInternal.addressSize();
+ }
+
+ public static int pageSize() {
+ return HBaseUnsafeInternal.pageSize();
+ }
+
+ public static Class<?> defineClass(String name, byte[] b, int off, int len,
ClassLoader loader,
+ ProtectionDomain protectionDomain) {
+ return HBaseUnsafeInternal.defineClass(name, b, off, len, loader,
protectionDomain);
+ }
+
+ public static Class<?> defineAnonymousClass(Class<?> hostClass, byte[] data,
Object[] cpPatches) {
+ return HBaseUnsafeInternal.defineAnonymousClass(hostClass, data,
cpPatches);
+ }
+
+ public static Object allocateInstance(Class<?> cls) throws
InstantiationException {
+ return HBaseUnsafeInternal.allocateInstance(cls);
+ }
+
+ public static void throwException(Throwable ee) {
+ HBaseUnsafeInternal.throwException(ee);
+ }
+
+ public static boolean compareAndSwapObject(Object o, long offset, Object
expected, Object x) {
+ return HBaseUnsafeInternal.compareAndSwapObject(o, offset, expected, x);
+ }
+
+ public static boolean compareAndSwapInt(Object o, long offset, int expected,
int x) {
+ return HBaseUnsafeInternal.compareAndSwapInt(o, offset, expected, x);
+ }
+
+ public static boolean compareAndSwapLong(Object o, long offset, long
expected, long x) {
+ return HBaseUnsafeInternal.compareAndSwapLong(o, offset, expected, x);
+ }
+
+ public static Object getObjectVolatile(Object o, long offset) {
+ return HBaseUnsafeInternal.getObjectVolatile(o, offset);
+ }
+
+ public static void putObjectVolatile(Object o, long offset, Object x) {
+ HBaseUnsafeInternal.putObjectVolatile(o, offset, x);
+ }
+
+ public static int getIntVolatile(Object o, long offset) {
+ return HBaseUnsafeInternal.getIntVolatile(o, offset);
+ }
+
+ public static void putIntVolatile(Object o, long offset, int x) {
+ HBaseUnsafeInternal.putIntVolatile(o, offset, x);
+ }
+
+ public static boolean getBooleanVolatile(Object o, long offset) {
+ return HBaseUnsafeInternal.getBooleanVolatile(o, offset);
+ }
+
+ public static void putBooleanVolatile(Object o, long offset, boolean x) {
+ HBaseUnsafeInternal.putBooleanVolatile(o, offset, x);
+ }
+
+ public static byte getByteVolatile(Object o, long offset) {
+ return HBaseUnsafeInternal.getByteVolatile(o, offset);
+ }
+
+ public static void putByteVolatile(Object o, long offset, byte x) {
+ HBaseUnsafeInternal.putByteVolatile(o, offset, x);
+ }
+
+ public static short getShortVolatile(Object o, long offset) {
+ return HBaseUnsafeInternal.getShortVolatile(o, offset);
+ }
+
+ public static void putShortVolatile(Object o, long offset, short x) {
+ HBaseUnsafeInternal.putShortVolatile(o, offset, x);
+ }
+
+ public static char getCharVolatile(Object o, long offset) {
+ return HBaseUnsafeInternal.getCharVolatile(o, offset);
+ }
+
+ public static void putCharVolatile(Object o, long offset, char x) {
+ HBaseUnsafeInternal.putCharVolatile(o, offset, x);
+ }
+
+ public static long getLongVolatile(Object o, long offset) {
+ return HBaseUnsafeInternal.getLongVolatile(o, offset);
+ }
+
+ public static void putLongVolatile(Object o, long offset, long x) {
+ HBaseUnsafeInternal.putLongVolatile(o, offset, x);
+ }
+
+ public static float getFloatVolatile(Object o, long offset) {
+ return HBaseUnsafeInternal.getFloatVolatile(o, offset);
+ }
+
+ public static void putFloatVolatile(Object o, long offset, float x) {
+ HBaseUnsafeInternal.putFloatVolatile(o, offset, x);
+ }
+
+ public static double getDoubleVolatile(Object o, long offset) {
+ return HBaseUnsafeInternal.getDoubleVolatile(o, offset);
+ }
+
+ public static void putDoubleVolatile(Object o, long offset, double x) {
+ HBaseUnsafeInternal.putDoubleVolatile(o, offset, x);
+ }
+
+ public static void putOrderedObject(Object o, long offset, Object x) {
+ HBaseUnsafeInternal.putOrderedObject(o, offset, x);
+ }
+
+ public static void putOrderedInt(Object o, long offset, int x) {
+ HBaseUnsafeInternal.putOrderedInt(o, offset, x);
+ }
+
+ public static void putOrderedLong(Object o, long offset, long x) {
+ HBaseUnsafeInternal.putOrderedLong(o, offset, x);
+ }
+
+ public static void unpark(Object thread) {
+ HBaseUnsafeInternal.unpark(thread);
+ }
+
+ public static void park(boolean isAbsolute, long time) {
+ HBaseUnsafeInternal.park(isAbsolute, time);
+ }
+
+ public static int getLoadAverage(double[] loadavg, int nelems) {
+ return HBaseUnsafeInternal.getLoadAverage(loadavg, nelems);
+ }
+
+ public static int getAndAddInt(Object o, long offset, int delta) {
+ return HBaseUnsafeInternal.getAndAddInt(o, offset, delta);
+ }
+
+ public static long getAndAddLong(Object o, long offset, long delta) {
+ return HBaseUnsafeInternal.getAndAddLong(o, offset, delta);
+ }
+
+ public static int getAndSetInt(Object o, long offset, int newValue) {
+ return HBaseUnsafeInternal.getAndSetInt(o, offset, newValue);
+ }
+
+ public static long getAndSetLong(Object o, long offset, long newValue) {
+ return HBaseUnsafeInternal.getAndSetLong(o, offset, newValue);
+ }
+
+ public static Object getAndSetObject(Object o, long offset, Object newValue)
{
+ return HBaseUnsafeInternal.getAndSetObject(o, offset, newValue);
+ }
+
+ public static void loadFence() {
+ HBaseUnsafeInternal.loadFence();
+ }
+
+ public static void storeFence() {
+ HBaseUnsafeInternal.storeFence();
+ }
+
+ public static void fullFence() {
+ HBaseUnsafeInternal.fullFence();
+ }
+
+}
diff --git
a/hbase-unsafe/src/main/java/org/apache/hadoop/hbase/unsafe/HBaseUnsafeInternal.java
b/hbase-unsafe/src/main/java/org/apache/hadoop/hbase/unsafe/HBaseUnsafeInternal.java
new file mode 100644
index 0000000..fede210
--- /dev/null
+++
b/hbase-unsafe/src/main/java/org/apache/hadoop/hbase/unsafe/HBaseUnsafeInternal.java
@@ -0,0 +1,414 @@
+/**
+ * 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.unsafe;
+
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import sun.misc.Unsafe;
+
+/**
+ * Delegate all the method in sun.misc.Unsafe.
+ */
+@SuppressWarnings("restriction")
+final class HBaseUnsafeInternal {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(HBaseUnsafeInternal.class);
+
+ private static final Unsafe UNSAFE;
+ static {
+ UNSAFE = (Unsafe) AccessController.doPrivileged(new
PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ try {
+ Field f = Unsafe.class.getDeclaredField("theUnsafe");
+ f.setAccessible(true);
+ return f.get(null);
+ } catch (Throwable e) {
+ LOG.warn("sun.misc.Unsafe is not accessible", e);
+ }
+ return null;
+ }
+ });
+ }
+
+ private HBaseUnsafeInternal() {
+ }
+
+ public static int getInt(Object o, long offset) {
+ return UNSAFE.getInt(o, offset);
+ }
+
+ public static void putInt(Object o, long offset, int x) {
+ UNSAFE.putInt(o, offset, x);
+ }
+
+ public static Object getObject(Object o, long offset) {
+ return UNSAFE.getObject(o, offset);
+ }
+
+ public static void putObject(Object o, long offset, Object x) {
+ UNSAFE.putObject(o, offset, x);
+ }
+
+ public static boolean getBoolean(Object o, long offset) {
+ return UNSAFE.getBoolean(o, offset);
+ }
+
+ public static void putBoolean(Object o, long offset, boolean x) {
+ UNSAFE.putBoolean(o, offset, x);
+ }
+
+ public static byte getByte(Object o, long offset) {
+ return UNSAFE.getByte(o, offset);
+ }
+
+ public static void putByte(Object o, long offset, byte x) {
+ UNSAFE.putByte(o, offset, x);
+ }
+
+ public static short getShort(Object o, long offset) {
+ return UNSAFE.getShort(o, offset);
+ }
+
+ public static void putShort(Object o, long offset, short x) {
+ UNSAFE.putShort(o, offset, x);
+ }
+
+ public static char getChar(Object o, long offset) {
+ return UNSAFE.getChar(o, offset);
+ }
+
+ public static void putChar(Object o, long offset, char x) {
+ UNSAFE.putChar(o, offset, x);
+ }
+
+ public static long getLong(Object o, long offset) {
+ return UNSAFE.getLong(o, offset);
+ }
+
+ public static void putLong(Object o, long offset, long x) {
+ UNSAFE.putLong(o, offset, x);
+ }
+
+ public static float getFloat(Object o, long offset) {
+ return UNSAFE.getFloat(o, offset);
+ }
+
+ public static void putFloat(Object o, long offset, float x) {
+ UNSAFE.putFloat(o, offset, x);
+ }
+
+ public static double getDouble(Object o, long offset) {
+ return UNSAFE.getDouble(o, offset);
+ }
+
+ public static void putDouble(Object o, long offset, double x) {
+ UNSAFE.putDouble(o, offset, x);
+ }
+
+ public static byte getByte(long address) {
+ return UNSAFE.getByte(address);
+ }
+
+ public static void putByte(long address, byte x) {
+ UNSAFE.putByte(address, x);
+ }
+
+ public static short getShort(long address) {
+ return UNSAFE.getShort(address);
+ }
+
+ public static void putShort(long address, short x) {
+ UNSAFE.putShort(address, x);
+ }
+
+ public static char getChar(long address) {
+ return UNSAFE.getChar(address);
+ }
+
+ public static void putChar(long address, char x) {
+ UNSAFE.putChar(address, x);
+ }
+
+ public static int getInt(long address) {
+ return UNSAFE.getInt(address);
+ }
+
+ public static void putInt(long address, int x) {
+ UNSAFE.putInt(address, x);
+ }
+
+ public static long getLong(long address) {
+ return UNSAFE.getLong(address);
+ }
+
+ public static void putLong(long address, long x) {
+ UNSAFE.putLong(address, x);
+ }
+
+ public static float getFloat(long address) {
+ return UNSAFE.getFloat(address);
+ }
+
+ public static void putFloat(long address, float x) {
+ UNSAFE.putFloat(address, x);
+ }
+
+ public static double getDouble(long address) {
+ return UNSAFE.getDouble(address);
+ }
+
+ public static void putDouble(long address, double x) {
+ UNSAFE.putDouble(address, x);
+ }
+
+ public static long getAddress(long address) {
+ return UNSAFE.getAddress(address);
+ }
+
+ public static void putAddress(long address, long x) {
+ UNSAFE.putAddress(address, x);
+ }
+
+ public static long allocateMemory(long bytes) {
+ return UNSAFE.allocateMemory(bytes);
+ }
+
+ public static long reallocateMemory(long address, long bytes) {
+ return UNSAFE.reallocateMemory(address, bytes);
+ }
+
+ public static void setMemory(Object o, long offset, long bytes, byte value) {
+ UNSAFE.setMemory(o, offset, bytes, value);
+ }
+
+ public static void setMemory(long address, long bytes, byte value) {
+ UNSAFE.setMemory(address, bytes, value);
+ }
+
+ public static void copyMemory(Object srcBase, long srcOffset, Object
destBase, long destOffset,
+ long bytes) {
+ UNSAFE.copyMemory(srcBase, srcOffset, destBase, destOffset, bytes);
+ }
+
+ public static void copyMemory(long srcAddress, long destAddress, long bytes)
{
+ UNSAFE.copyMemory(srcAddress, destAddress, bytes);
+ }
+
+ public static void freeMemory(long address) {
+ UNSAFE.freeMemory(address);
+ }
+
+ public static long staticFieldOffset(Field f) {
+ return UNSAFE.staticFieldOffset(f);
+ }
+
+ public static long objectFieldOffset(Field f) {
+ return UNSAFE.objectFieldOffset(f);
+ }
+
+ public static Object staticFieldBase(Field f) {
+ return UNSAFE.staticFieldBase(f);
+ }
+
+ public static boolean shouldBeInitialized(Class<?> c) {
+ return UNSAFE.shouldBeInitialized(c);
+ }
+
+ public static void ensureClassInitialized(Class<?> c) {
+ UNSAFE.ensureClassInitialized(c);
+ }
+
+ public static int arrayBaseOffset(Class<?> arrayClass) {
+ return UNSAFE.arrayBaseOffset(arrayClass);
+ }
+
+ public static int arrayIndexScale(Class<?> arrayClass) {
+ return UNSAFE.arrayIndexScale(arrayClass);
+ }
+
+ public static int addressSize() {
+ return UNSAFE.addressSize();
+ }
+
+ public static int pageSize() {
+ return UNSAFE.pageSize();
+ }
+
+ public static Class<?> defineClass(String name, byte[] b, int off, int len,
ClassLoader loader,
+ ProtectionDomain protectionDomain) {
+ return UNSAFE.defineClass(name, b, off, len, loader, protectionDomain);
+ }
+
+ public static Class<?> defineAnonymousClass(Class<?> hostClass, byte[] data,
Object[] cpPatches) {
+ return UNSAFE.defineAnonymousClass(hostClass, data, cpPatches);
+ }
+
+ public static Object allocateInstance(Class<?> cls) throws
InstantiationException {
+ return UNSAFE.allocateInstance(cls);
+ }
+
+ public static void throwException(Throwable ee) {
+ UNSAFE.throwException(ee);
+ }
+
+ public static boolean compareAndSwapObject(Object o, long offset, Object
expected, Object x) {
+ return UNSAFE.compareAndSwapObject(o, offset, expected, x);
+ }
+
+ public static boolean compareAndSwapInt(Object o, long offset, int expected,
int x) {
+ return UNSAFE.compareAndSwapInt(o, offset, expected, x);
+ }
+
+ public static boolean compareAndSwapLong(Object o, long offset, long
expected, long x) {
+ return UNSAFE.compareAndSwapLong(o, offset, expected, x);
+ }
+
+ public static Object getObjectVolatile(Object o, long offset) {
+ return UNSAFE.getObjectVolatile(o, offset);
+ }
+
+ public static void putObjectVolatile(Object o, long offset, Object x) {
+ UNSAFE.putObjectVolatile(o, offset, x);
+ }
+
+ public static int getIntVolatile(Object o, long offset) {
+ return UNSAFE.getIntVolatile(o, offset);
+ }
+
+ public static void putIntVolatile(Object o, long offset, int x) {
+ UNSAFE.putIntVolatile(o, offset, x);
+ }
+
+ public static boolean getBooleanVolatile(Object o, long offset) {
+ return UNSAFE.getBooleanVolatile(o, offset);
+ }
+
+ public static void putBooleanVolatile(Object o, long offset, boolean x) {
+ UNSAFE.putBooleanVolatile(o, offset, x);
+ }
+
+ public static byte getByteVolatile(Object o, long offset) {
+ return UNSAFE.getByteVolatile(o, offset);
+ }
+
+ public static void putByteVolatile(Object o, long offset, byte x) {
+ UNSAFE.putByteVolatile(o, offset, x);
+ }
+
+ public static short getShortVolatile(Object o, long offset) {
+ return UNSAFE.getShortVolatile(o, offset);
+ }
+
+ public static void putShortVolatile(Object o, long offset, short x) {
+ UNSAFE.putShortVolatile(o, offset, x);
+ }
+
+ public static char getCharVolatile(Object o, long offset) {
+ return UNSAFE.getCharVolatile(o, offset);
+ }
+
+ public static void putCharVolatile(Object o, long offset, char x) {
+ UNSAFE.putCharVolatile(o, offset, x);
+ }
+
+ public static long getLongVolatile(Object o, long offset) {
+ return UNSAFE.getLongVolatile(o, offset);
+ }
+
+ public static void putLongVolatile(Object o, long offset, long x) {
+ UNSAFE.putLongVolatile(o, offset, x);
+ }
+
+ public static float getFloatVolatile(Object o, long offset) {
+ return UNSAFE.getFloatVolatile(o, offset);
+ }
+
+ public static void putFloatVolatile(Object o, long offset, float x) {
+ UNSAFE.putFloatVolatile(o, offset, x);
+ }
+
+ public static double getDoubleVolatile(Object o, long offset) {
+ return UNSAFE.getDoubleVolatile(o, offset);
+ }
+
+ public static void putDoubleVolatile(Object o, long offset, double x) {
+ UNSAFE.putDoubleVolatile(o, offset, x);
+ }
+
+ public static void putOrderedObject(Object o, long offset, Object x) {
+ UNSAFE.putOrderedObject(o, offset, x);
+ }
+
+ public static void putOrderedInt(Object o, long offset, int x) {
+ UNSAFE.putOrderedInt(o, offset, x);
+ }
+
+ public static void putOrderedLong(Object o, long offset, long x) {
+ UNSAFE.putOrderedLong(o, offset, x);
+ }
+
+ public static void unpark(Object thread) {
+ UNSAFE.unpark(thread);
+ }
+
+ public static void park(boolean isAbsolute, long time) {
+ UNSAFE.park(isAbsolute, time);
+ }
+
+ public static int getLoadAverage(double[] loadavg, int nelems) {
+ return UNSAFE.getLoadAverage(loadavg, nelems);
+ }
+
+ public static int getAndAddInt(Object o, long offset, int delta) {
+ return UNSAFE.getAndAddInt(o, offset, delta);
+ }
+
+ public static long getAndAddLong(Object o, long offset, long delta) {
+ return UNSAFE.getAndAddLong(o, offset, delta);
+ }
+
+ public static int getAndSetInt(Object o, long offset, int newValue) {
+ return UNSAFE.getAndSetInt(o, offset, newValue);
+ }
+
+ public static long getAndSetLong(Object o, long offset, long newValue) {
+ return UNSAFE.getAndSetLong(o, offset, newValue);
+ }
+
+ public static Object getAndSetObject(Object o, long offset, Object newValue)
{
+ return UNSAFE.getAndSetObject(o, offset, newValue);
+ }
+
+ public static void loadFence() {
+ UNSAFE.loadFence();
+ }
+
+ public static void storeFence() {
+ UNSAFE.storeFence();
+ }
+
+ public static void fullFence() {
+ UNSAFE.fullFence();
+ }
+
+}
diff --git
a/hbase-unsafe/src/test/java/org/apache/hadoop/hbase/unsafe/TestHBaseUnsafe.java
b/hbase-unsafe/src/test/java/org/apache/hadoop/hbase/unsafe/TestHBaseUnsafe.java
new file mode 100644
index 0000000..699996b
--- /dev/null
+++
b/hbase-unsafe/src/test/java/org/apache/hadoop/hbase/unsafe/TestHBaseUnsafe.java
@@ -0,0 +1,35 @@
+/**
+ * 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.unsafe;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
+import org.junit.Test;
+
+public class TestHBaseUnsafe {
+
+ @Test
+ public void test() {
+ assumeTrue(HBaseUnsafe.isAvailable());
+ byte[] arr = new byte[4];
+ int arrayBaseOffset = HBaseUnsafe.arrayBaseOffset(arr.getClass());
+ HBaseUnsafe.putInt(arr, arrayBaseOffset, 123456);
+ assertEquals(123456, HBaseUnsafe.getInt(arr, arrayBaseOffset));
+ }
+}
diff --git a/pom.xml b/pom.xml
index c15cd20..377c9c0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,6 +61,7 @@
<module>hbase-shaded-jersey</module>
<module>hbase-shaded-jackson-jaxrs-json-provider</module>
<module>hbase-noop-htrace</module>
+ <module>hbase-unsafe</module>
</modules>
<scm>
<connection>scm:git:git://git.apache.org/hbase-thirdparty.git</connection>
@@ -239,6 +240,10 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>