1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.util;
19
20 import java.lang.reflect.Field;
21 import java.lang.reflect.Method;
22 import java.nio.ByteBuffer;
23 import java.nio.ByteOrder;
24 import java.security.AccessController;
25 import java.security.PrivilegedAction;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.hbase.classification.InterfaceAudience;
30 import org.apache.hadoop.hbase.classification.InterfaceStability;
31
32 import sun.misc.Unsafe;
33 import sun.nio.ch.DirectBuffer;
34
35 @InterfaceAudience.Private
36 @InterfaceStability.Evolving
37 public final class UnsafeAccess {
38
39 private static final Log LOG = LogFactory.getLog(UnsafeAccess.class);
40
41 public static final Unsafe theUnsafe;
42 private static boolean unaligned = false;
43
44
45 public static final int BYTE_ARRAY_BASE_OFFSET;
46
47
48
49
50 static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L;
51 static {
52 theUnsafe = (Unsafe) AccessController.doPrivileged(new PrivilegedAction<Object>() {
53 @Override
54 public Object run() {
55 try {
56 Field f = Unsafe.class.getDeclaredField("theUnsafe");
57 f.setAccessible(true);
58 return f.get(null);
59 } catch (Throwable e) {
60 LOG.warn("sun.misc.Unsafe is not accessible", e);
61 }
62 return null;
63 }
64 });
65
66 if(theUnsafe != null){
67 BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);
68 String arch = System.getProperty("os.arch");
69 if ("ppc64".equals(arch) || "ppc64le".equals(arch)) {
70
71 unaligned = true;
72 }
73 else {
74 try {
75
76 Class<?> clazz = Class.forName("java.nio.Bits");
77 Method m = clazz.getDeclaredMethod("unaligned");
78 m.setAccessible(true);
79 unaligned = (boolean) m.invoke(null);
80
81
82
83 if (System.getProperty("os.arch").equalsIgnoreCase("ppc64le")) {
84 unaligned = true;
85 }
86 } catch (Exception e) {
87 unaligned = false;
88 }
89 }
90 } else{
91 BYTE_ARRAY_BASE_OFFSET = -1;
92 }
93 }
94
95 private UnsafeAccess(){}
96
97 public static boolean isAvailable() {
98 return theUnsafe != null;
99 }
100
101
102
103
104
105 public static boolean unaligned() {
106 return unaligned;
107 }
108
109
110
111
112
113
114
115
116
117
118
119 public static void copy(byte[] src, int srcOffset, ByteBuffer dest, int destOffset, int length) {
120 long destAddress = destOffset;
121 Object destBase = null;
122 if (dest.isDirect()) {
123 destAddress = destAddress + ((DirectBuffer) dest).address();
124 } else {
125 destAddress = destAddress + BYTE_ARRAY_BASE_OFFSET + dest.arrayOffset();
126 destBase = dest.array();
127 }
128 long srcAddress = srcOffset + BYTE_ARRAY_BASE_OFFSET;
129 unsafeCopy(src, srcAddress, destBase, destAddress, length);
130 }
131
132 private static void unsafeCopy(Object src, long srcAddr, Object dst, long destAddr, long len) {
133 while (len > 0) {
134 long size = (len > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : len;
135 theUnsafe.copyMemory(src, srcAddr, dst, destAddr, len);
136 len -= size;
137 srcAddr += size;
138 destAddr += size;
139 }
140 }
141
142
143
144
145
146
147
148
149
150
151
152 public static void copy(ByteBuffer src, int srcOffset, byte[] dest, int destOffset,
153 int length) {
154 long srcAddress = srcOffset;
155 Object srcBase = null;
156 if (src.isDirect()) {
157 srcAddress = srcAddress + ((DirectBuffer) src).address();
158 } else {
159 srcAddress = srcAddress + BYTE_ARRAY_BASE_OFFSET + src.arrayOffset();
160 srcBase = src.array();
161 }
162 long destAddress = destOffset + BYTE_ARRAY_BASE_OFFSET;
163 unsafeCopy(srcBase, srcAddress, dest, destAddress, length);
164 }
165
166
167
168
169
170
171
172
173
174
175
176 public static void copy(ByteBuffer src, int srcOffset, ByteBuffer dest, int destOffset,
177 int length) {
178 long srcAddress, destAddress;
179 Object srcBase = null, destBase = null;
180 if (src.isDirect()) {
181 srcAddress = srcOffset + ((DirectBuffer) src).address();
182 } else {
183 srcAddress = srcOffset + src.arrayOffset() + BYTE_ARRAY_BASE_OFFSET;
184 srcBase = src.array();
185 }
186 if (dest.isDirect()) {
187 destAddress = destOffset + ((DirectBuffer) dest).address();
188 } else {
189 destAddress = destOffset + BYTE_ARRAY_BASE_OFFSET + dest.arrayOffset();
190 destBase = dest.array();
191 }
192 unsafeCopy(srcBase, srcAddress, destBase, destAddress, length);
193 }
194 }