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.security.AccessController;
23 import java.security.PrivilegedAction;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.apache.hadoop.hbase.classification.InterfaceAudience;
28
29 @InterfaceAudience.Private
30 public class UnsafeAvailChecker {
31
32 private static final String CLASS_NAME = "sun.misc.Unsafe";
33 private static final Log LOG = LogFactory.getLog(UnsafeAvailChecker.class);
34 private static boolean avail = false;
35 private static boolean unaligned = false;
36
37 static {
38 avail = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
39 @Override
40 public Boolean run() {
41 try {
42 Class<?> clazz = Class.forName(CLASS_NAME);
43 Field f = clazz.getDeclaredField("theUnsafe");
44 f.setAccessible(true);
45 Object theUnsafe = f.get(null);
46 if (theUnsafe == null) {
47 LOG.warn("Could not get static instance from sun.misc.Unsafe");
48 return false;
49 }
50
51 Method m;
52 try {
53 m = clazz.getDeclaredMethod("arrayBaseOffset", Class.class);
54 if (m == null) {
55 LOG.warn("sun.misc.Unsafe is missing arrayBaseOffset(Class)");
56 return false;
57 }
58 m = clazz.getDeclaredMethod("copyMemory", Object.class, long.class, Object.class,
59 long.class, long.class);
60 if (m == null) {
61 LOG.warn("sun.misc.Unsafe is missing copyMemory(Object,long,Object,long,long)");
62 return false;
63 }
64 m = clazz.getDeclaredMethod("getByte", Object.class, long.class);
65 if (m == null) {
66 LOG.warn("sun.misc.Unsafe is missing getByte(Object,long)");
67 return false;
68 }
69 m = clazz.getDeclaredMethod("getShort", long.class);
70 if (m == null) {
71 LOG.warn("sun.misc.Unsafe is missing getShort(long)");
72 return false;
73 }
74 m = clazz.getDeclaredMethod("getShort", Object.class, long.class);
75 if (m == null) {
76 LOG.warn("sun.misc.Unsafe is missing getShort(Object,long)");
77 return false;
78 }
79 m = clazz.getDeclaredMethod("getInt", long.class);
80 if (m == null) {
81 LOG.warn("sun.misc.Unsafe is missing getInt(long)");
82 return false;
83 }
84 m = clazz.getDeclaredMethod("getInt", Object.class, long.class);
85 if (m == null) {
86 LOG.warn("sun.misc.Unsafe is missing getInt(Object,long)");
87 return false;
88 }
89 m = clazz.getDeclaredMethod("getLong", long.class);
90 if (m == null) {
91 LOG.warn("sun.misc.Unsafe is missing getLong(long)");
92 return false;
93 }
94 m = clazz.getDeclaredMethod("getLong", Object.class, long.class);
95 if (m == null) {
96 LOG.warn("sun.misc.Unsafe is missing getLong(Object,long)");
97 return false;
98 }
99 m = clazz.getDeclaredMethod("putByte", long.class, byte.class);
100 if (m == null) {
101 LOG.warn("sun.misc.Unsafe is missing putByte(long,byte)");
102 return false;
103 }
104 m = clazz.getDeclaredMethod("putByte", Object.class, long.class, byte.class);
105 if (m == null) {
106 LOG.warn("sun.misc.Unsafe is missing putByte(Object,long,byte)");
107 return false;
108 }
109 m = clazz.getDeclaredMethod("putShort", long.class, short.class);
110 if (m == null) {
111 LOG.warn("sun.misc.Unsafe is missing putShort(long,short)");
112 return false;
113 }
114 m = clazz.getDeclaredMethod("putShort", Object.class, long.class, short.class);
115 if (m == null) {
116 LOG.warn("sun.misc.Unsafe is missing putShort(Object,long,short)");
117 return false;
118 }
119 m = clazz.getDeclaredMethod("putInt", long.class, int.class);
120 if (m == null) {
121 LOG.warn("sun.misc.Unsafe is missing putInt(long,int)");
122 return false;
123 }
124 m = clazz.getDeclaredMethod("putInt", Object.class, long.class, int.class);
125 if (m == null) {
126 LOG.warn("sun.misc.Unsafe is missing putInt(Object,long,int)");
127 return false;
128 }
129 m = clazz.getDeclaredMethod("putLong", long.class, long.class);
130 if (m == null) {
131 LOG.warn("sun.misc.Unsafe is missing putLong(long,long)");
132 return false;
133 }
134 m = clazz.getDeclaredMethod("putLong", Object.class, long.class, long.class);
135 if (m == null) {
136 LOG.warn("sun.misc.Unsafe is missing putLong(Object,long,long)");
137 return false;
138 }
139
140 return true;
141 } catch (Throwable e) {
142 LOG.warn("sun.misc.Unsafe is missing one or more required methods", e);
143 }
144 } catch (Throwable e) {
145 LOG.warn("sun.misc.Unsafe is not available/accessible", e);
146 }
147 return false;
148 }
149 });
150
151 if (avail) {
152 String arch = System.getProperty("os.arch");
153 if ("ppc64".equals(arch) || "ppc64le".equals(arch)) {
154
155 unaligned = true;
156 } else {
157 try {
158
159 Class<?> clazz = Class.forName("java.nio.Bits");
160 Method m = clazz.getDeclaredMethod("unaligned");
161 m.setAccessible(true);
162 unaligned = (Boolean) m.invoke(null);
163 } catch (Exception e) {
164 LOG.warn("java.nio.Bits#unaligned() check failed."
165 + "Unsafe based read/write of primitive types won't be used", e);
166 }
167 }
168 }
169 }
170
171
172
173
174
175 public static boolean isAvailable() {
176 return avail;
177 }
178
179
180
181
182
183 public static boolean unaligned() {
184 return unaligned;
185 }
186
187 private UnsafeAvailChecker() {
188
189 }
190 }