1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.util.internal;
17
18 import io.netty.util.internal.logging.InternalLogger;
19 import io.netty.util.internal.logging.InternalLoggerFactory;
20
21 import java.lang.invoke.MethodHandle;
22 import java.lang.invoke.MethodHandles;
23 import java.lang.reflect.Field;
24 import java.security.AccessController;
25 import java.security.PrivilegedAction;
26 import java.util.ArrayList;
27 import java.util.List;
28
29 import static java.lang.invoke.MethodType.methodType;
30
31
32
33
34 final class SunMiscUnsafeAccess {
35
36 private static final InternalLogger logger = InternalLoggerFactory.getInstance(SunMiscUnsafeAccess.class);
37 private static final String SUN_MISC_UNSAFE_CLASS_NAME = "sun.misc.Unsafe";
38 private static final Throwable EXPLICIT_NO_UNSAFE_CAUSE = explicitNoUnsafeCause0();
39 private static final Throwable UNSAFE_UNAVAILABILITY_CAUSE;
40 private static final MethodHandle UNSAFE_ALLOCATE_MEMORY_HANDLE;
41 private static final MethodHandle UNSAFE_COPY_MEMORY_WITH_OBJECT_HANDLE;
42 private static final MethodHandle UNSAFE_COPY_MEMORY_WITH_LONG_HANDLE;
43 private static final MethodHandle UNSAFE_OBJECT_FIELD_OFFSET_HANDLE;
44 private static final MethodHandle UNSAFE_REALLOCATE_MEMORY_HANDLE;
45 private static final MethodHandle UNSAFE_FREE_MEMORY_HANDLE;
46 private static final MethodHandle UNSAFE_SET_MEMORY_WITH_LONG_HANDLE;
47 private static final MethodHandle UNSAFE_SET_MEMORY_WITH_OBJECT_HANDLE;
48 private static final MethodHandle UNSAFE_GET_BYTE_WITH_LONG_HANDLE;
49 private static final MethodHandle UNSAFE_GET_BYTE_WITH_OBJECT_HANDLE;
50 private static final MethodHandle UNSAFE_GET_CHAR_WITH_OBJECT_HANDLE;
51 private static final MethodHandle UNSAFE_GET_SHORT_WITH_LONG_HANDLE;
52 private static final MethodHandle UNSAFE_GET_SHORT_WITH_OBJECT_HANDLE;
53 private static final MethodHandle UNSAFE_GET_INT_WITH_LONG_HANDLE;
54 private static final MethodHandle UNSAFE_GET_INT_WITH_OBJECT_HANDLE;
55 private static final MethodHandle UNSAFE_GET_INT_VOLATILE_WITH_OBJECT_HANDLE;
56 private static final MethodHandle UNSAFE_GET_LONG_WITH_LONG_HANDLE;
57 private static final MethodHandle UNSAFE_GET_LONG_WITH_OBJECT_HANDLE;
58 private static final MethodHandle UNSAFE_GET_OBJECT_WITH_OBJECT_HANDLE;
59 private static final MethodHandle UNSAFE_PUT_BYTE_WITH_LONG_HANDLE;
60 private static final MethodHandle UNSAFE_PUT_BYTE_WITH_OBJECT_HANDLE;
61 private static final MethodHandle UNSAFE_PUT_SHORT_WITH_LONG_HANDLE;
62 private static final MethodHandle UNSAFE_PUT_SHORT_WITH_OBJECT_HANDLE;
63 private static final MethodHandle UNSAFE_PUT_INT_WITH_LONG_HANDLE;
64 private static final MethodHandle UNSAFE_PUT_INT_WITH_OBJECT_HANDLE;
65 private static final MethodHandle UNSAFE_PUT_ORDERED_INT_WITH_OBJECT_HANDLE;
66 private static final MethodHandle UNSAFE_PUT_LONG_WITH_LONG_HANDLE;
67 private static final MethodHandle UNSAFE_PUT_LONG_WITH_OBJECT_HANDLE;
68 private static final MethodHandle UNSAFE_PUT_OBJECT_WITH_OBJECT_HANDLE;
69 private static final MethodHandle UNSAFE_ADDRESS_SIZE_HANDLE;
70 private static final MethodHandle UNSAFE_STORE_FENCE_HANDLE;
71 private static final MethodHandle UNSAFE_ARRAY_BASE_OFFSET_HANDLE;
72 private static final MethodHandle UNSAFE_ARRAY_INDEX_SCALE_HANDLE;
73 private static final MethodHandle UNSAFE_STATIC_FIELD_OFFSET_HANDLE;
74 private static final MethodHandle UNSAFE_STATIC_FIELD_BASE_HANDLE;
75 private static final MethodHandle UNSAFE_GET_BOOLEAN_WITH_OBJECT_HANDLE;
76
77
78 static final Object UNSAFE;
79
80 static {
81 MethodHandles.Lookup lookup = MethodHandles.lookup();
82 Throwable unsafeUnavailabilityCause = null;
83 Object unsafe;
84 MethodHandle allocateMemoryHandle = null;
85 MethodHandle copyMemoryWithLongHandle = null;
86 MethodHandle copyMemoryWithObjectHandle = null;
87 MethodHandle objectFieldOffsetHandle = null;
88 MethodHandle staticFieldOffsetHandle = null;
89 MethodHandle staticFieldBaseHandle = null;
90 MethodHandle arrayBaseOffsetHandle = null;
91 MethodHandle arrayIndexScaleHandle = null;
92 MethodHandle reallocateMemoryHandle = null;
93 MethodHandle freeMemoryHandle = null;
94 MethodHandle setMemoryWithLongHandle = null;
95 MethodHandle setMemoryWithObjectHandle = null;
96 MethodHandle getBooleanWithObjectHandle = null;
97 MethodHandle getByteWithLongHandle = null;
98 MethodHandle getByteWithObjectHandle = null;
99 MethodHandle getCharWithObjectHandle = null;
100 MethodHandle getShortWithLongHandle = null;
101 MethodHandle getShortWithObjectHandle = null;
102 MethodHandle getIntWithLongHandle = null;
103 MethodHandle getIntWithObjectHandle = null;
104 MethodHandle getIntVolatileWithObjectHandle = null;
105 MethodHandle getLongWithLongHandle = null;
106 MethodHandle getLongWithObjectHandle = null;
107 MethodHandle getObjectWithObjectHandle = null;
108 MethodHandle putByteWithLongHandle = null;
109 MethodHandle putByteWithObjectHandle = null;
110 MethodHandle putShortWithLongHandle = null;
111 MethodHandle putShortWithObjectHandle = null;
112 MethodHandle putIntWithLongHandle = null;
113 MethodHandle putIntWithObjectHandle = null;
114 MethodHandle putOrderedIntWithObjectHandle = null;
115 MethodHandle putLongWithLongHandle = null;
116 MethodHandle putLongWithObjectHandle = null;
117 MethodHandle putObjectWithObjectHandle = null;
118 MethodHandle addressSizeHandle = null;
119 MethodHandle storeFenceHandle = null;
120
121 if ((unsafeUnavailabilityCause = EXPLICIT_NO_UNSAFE_CAUSE) != null) {
122 unsafe = null;
123 } else {
124
125 final Object maybeUnsafe = AccessController.doPrivileged(new PrivilegedAction<Object>() {
126 @Override
127 public Object run() {
128 try {
129 Class<?> unsafeClass = Class.forName(SUN_MISC_UNSAFE_CLASS_NAME);
130 final Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
131
132
133 Throwable cause = ReflectionUtil.trySetAccessible(unsafeField, false);
134 if (cause != null) {
135 return cause;
136 }
137
138 return unsafeField.get(null);
139 } catch (NoSuchFieldException | SecurityException |
140 IllegalAccessException | ClassNotFoundException e) {
141 return e;
142 } catch (NoClassDefFoundError e) {
143
144
145 return e;
146 }
147 }
148 });
149
150
151
152
153
154 if (maybeUnsafe instanceof Throwable) {
155 unsafe = null;
156 unsafeUnavailabilityCause = (Throwable) maybeUnsafe;
157 if (logger.isTraceEnabled()) {
158 logger.debug("{}: unavailable", SUN_MISC_UNSAFE_CLASS_NAME, maybeUnsafe);
159 } else {
160 logger.debug("{}.theUnsafe: unavailable: {}", SUN_MISC_UNSAFE_CLASS_NAME,
161 unsafeUnavailabilityCause.getMessage());
162 }
163 } else {
164 unsafe = maybeUnsafe;
165 logger.debug("sun.misc.Unsafe.theUnsafe: available");
166 }
167
168
169
170
171
172
173 if (unsafe != null) {
174 final Object finalUnsafe = unsafe;
175 final Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
176 @Override
177 public Object run() {
178 try {
179
180 Class<?> cls = finalUnsafe.getClass();
181 List<MethodHandle> methodHandles = new ArrayList<>();
182 MethodHandle allocateMemoryHandle = lookup.findVirtual(cls, "allocateMemory",
183 methodType(long.class, long.class)).bindTo(finalUnsafe);
184 methodHandles.add(allocateMemoryHandle);
185 methodHandles.add(
186 lookup.findVirtual(cls, "copyMemory",
187 methodType(void.class, long.class, long.class, long.class))
188 .bindTo(finalUnsafe)
189 );
190 methodHandles.add(
191 lookup.findVirtual(cls, "copyMemory",
192 methodType(void.class, Object.class, long.class, Object.class,
193 long.class, long.class))
194 .bindTo(finalUnsafe)
195 );
196 methodHandles.add(
197 lookup.findVirtual(cls, "objectFieldOffset",
198 methodType(long.class, Field.class))
199 .bindTo(finalUnsafe)
200 );
201 methodHandles.add(
202 lookup.findVirtual(cls, "staticFieldOffset",
203 methodType(long.class, Field.class))
204 .bindTo(finalUnsafe)
205 );
206 methodHandles.add(
207 lookup.findVirtual(cls, "staticFieldBase",
208 methodType(Object.class, Field.class))
209 .bindTo(finalUnsafe)
210 );
211 methodHandles.add(
212 lookup.findVirtual(cls, "arrayBaseOffset",
213 methodType(int.class, Class.class))
214 .bindTo(finalUnsafe)
215 );
216 methodHandles.add(
217 lookup.findVirtual(cls, "arrayIndexScale",
218 methodType(int.class, Class.class))
219 .bindTo(finalUnsafe)
220 );
221 methodHandles.add(
222 lookup.findVirtual(cls, "reallocateMemory",
223 methodType(long.class, long.class, long.class))
224 .bindTo(finalUnsafe)
225 );
226 MethodHandle freeMemoryHandle = lookup.findVirtual(cls, "freeMemory",
227 methodType(void.class, long.class)).bindTo(finalUnsafe);
228 methodHandles.add(freeMemoryHandle);
229 methodHandles.add(
230 lookup.findVirtual(cls, "setMemory",
231 methodType(void.class, long.class, long.class, byte.class))
232 .bindTo(finalUnsafe)
233 );
234 methodHandles.add(
235 lookup.findVirtual(cls, "setMemory",
236 methodType(void.class, Object.class, long.class,
237 long.class, byte.class))
238 .bindTo(finalUnsafe)
239 );
240 methodHandles.add(
241 lookup.findVirtual(cls, "getBoolean",
242 methodType(boolean.class, Object.class, long.class))
243 .bindTo(finalUnsafe)
244 );
245 methodHandles.add(
246 lookup.findVirtual(cls, "getByte",
247 methodType(byte.class, long.class))
248 .bindTo(finalUnsafe)
249 );
250 methodHandles.add(
251 lookup.findVirtual(cls, "getByte",
252 methodType(byte.class, Object.class, long.class))
253 .bindTo(finalUnsafe)
254 );
255 methodHandles.add(
256 lookup.findVirtual(cls, "getChar",
257 methodType(char.class, Object.class, long.class))
258 .bindTo(finalUnsafe)
259 );
260 methodHandles.add(
261 lookup.findVirtual(cls, "getShort",
262 methodType(short.class, long.class))
263 .bindTo(finalUnsafe)
264 );
265 methodHandles.add(
266 lookup.findVirtual(cls, "getShort",
267 methodType(short.class, Object.class, long.class))
268 .bindTo(finalUnsafe)
269 );
270 methodHandles.add(
271 lookup.findVirtual(cls, "getInt",
272 methodType(int.class, long.class))
273 .bindTo(finalUnsafe)
274 );
275 methodHandles.add(
276 lookup.findVirtual(cls, "getInt",
277 methodType(int.class, Object.class, long.class))
278 .bindTo(finalUnsafe)
279 );
280 methodHandles.add(
281 lookup.findVirtual(cls, "getIntVolatile",
282 methodType(int.class, Object.class, long.class))
283 .bindTo(finalUnsafe)
284 );
285 methodHandles.add(
286 lookup.findVirtual(cls, "getLong",
287 methodType(long.class, long.class))
288 .bindTo(finalUnsafe)
289 );
290 methodHandles.add(
291 lookup.findVirtual(cls, "getLong",
292 methodType(long.class, Object.class, long.class))
293 .bindTo(finalUnsafe)
294 );
295 methodHandles.add(
296 lookup.findVirtual(cls, "getObject",
297 methodType(Object.class, Object.class, long.class))
298 .bindTo(finalUnsafe)
299 );
300 methodHandles.add(
301 lookup.findVirtual(cls, "putByte",
302 methodType(void.class, long.class, byte.class))
303 .bindTo(finalUnsafe)
304 );
305 methodHandles.add(
306 lookup.findVirtual(cls, "putByte",
307 methodType(void.class, Object.class, long.class, byte.class))
308 .bindTo(finalUnsafe)
309 );
310 methodHandles.add(
311 lookup.findVirtual(cls, "putShort",
312 methodType(void.class, long.class, short.class))
313 .bindTo(finalUnsafe)
314 );
315 methodHandles.add(
316 lookup.findVirtual(cls, "putShort",
317 methodType(void.class, Object.class, long.class, short.class))
318 .bindTo(finalUnsafe)
319 );
320 methodHandles.add(
321 lookup.findVirtual(cls, "putInt",
322 methodType(void.class, long.class, int.class))
323 .bindTo(finalUnsafe)
324 );
325 methodHandles.add(
326 lookup.findVirtual(cls, "putInt",
327 methodType(void.class, Object.class, long.class, int.class))
328 .bindTo(finalUnsafe)
329 );
330 methodHandles.add(
331 lookup.findVirtual(cls, "putOrderedInt",
332 methodType(void.class, Object.class, long.class, int.class))
333 .bindTo(finalUnsafe)
334 );
335 MethodHandle putLongHandle = lookup.findVirtual(cls, "putLong",
336 methodType(void.class, long.class, long.class)).bindTo(finalUnsafe);
337 methodHandles.add(putLongHandle);
338 methodHandles.add(
339 lookup.findVirtual(cls, "putLong",
340 methodType(void.class, Object.class, long.class, long.class))
341 .bindTo(finalUnsafe)
342 );
343 methodHandles.add(
344 lookup.findVirtual(cls, "putObject",
345 methodType(void.class, Object.class, long.class, Object.class))
346 .bindTo(finalUnsafe)
347 );
348 methodHandles.add(
349 lookup.findVirtual(cls, "addressSize",
350 methodType(int.class))
351 .bindTo(finalUnsafe)
352 );
353 methodHandles.add(
354 lookup.findVirtual(cls, "storeFence",
355 methodType(void.class))
356 .bindTo(finalUnsafe)
357 );
358
359
360
361 long address = (long) allocateMemoryHandle.invokeExact((long) 8);
362 putLongHandle.invokeExact(address, (long) 42);
363 freeMemoryHandle.invokeExact(address);
364 return methodHandles;
365 } catch (Throwable cause) {
366 return cause;
367 }
368 }
369 });
370
371 if (maybeException instanceof Throwable) {
372
373 unsafe = null;
374 unsafeUnavailabilityCause = (Throwable) maybeException;
375 if (logger.isTraceEnabled()) {
376 logger.debug("{} method unavailable:", SUN_MISC_UNSAFE_CLASS_NAME, unsafeUnavailabilityCause);
377 } else {
378 logger.debug("{} method unavailable: {}", SUN_MISC_UNSAFE_CLASS_NAME,
379 ((Throwable) maybeException).getMessage());
380 }
381 } else {
382 logger.debug("{} base methods: all available", SUN_MISC_UNSAFE_CLASS_NAME);
383 @SuppressWarnings("unchecked") List<MethodHandle> handles = (List<MethodHandle>) maybeException;
384
385 int idx = 0;
386 allocateMemoryHandle = handles.get(idx++);
387 copyMemoryWithLongHandle = handles.get(idx++);
388 copyMemoryWithObjectHandle = handles.get(idx++);
389 objectFieldOffsetHandle = handles.get(idx++);
390 staticFieldOffsetHandle = handles.get(idx++);
391 staticFieldBaseHandle = handles.get(idx++);
392 arrayBaseOffsetHandle = handles.get(idx++);
393 arrayIndexScaleHandle = handles.get(idx++);
394 reallocateMemoryHandle = handles.get(idx++);
395 freeMemoryHandle = handles.get(idx++);
396 setMemoryWithLongHandle = handles.get(idx++);
397 setMemoryWithObjectHandle = handles.get(idx++);
398 getBooleanWithObjectHandle = handles.get(idx++);
399 getByteWithLongHandle = handles.get(idx++);
400 getByteWithObjectHandle = handles.get(idx++);
401 getCharWithObjectHandle = handles.get(idx++);
402 getShortWithLongHandle = handles.get(idx++);
403 getShortWithObjectHandle = handles.get(idx++);
404 getIntWithLongHandle = handles.get(idx++);
405 getIntWithObjectHandle = handles.get(idx++);
406 getIntVolatileWithObjectHandle = handles.get(idx++);
407 getLongWithLongHandle = handles.get(idx++);
408 getLongWithObjectHandle = handles.get(idx++);
409 getObjectWithObjectHandle = handles.get(idx++);
410 putByteWithLongHandle = handles.get(idx++);
411 putByteWithObjectHandle = handles.get(idx++);
412 putShortWithLongHandle = handles.get(idx++);
413 putShortWithObjectHandle = handles.get(idx++);
414 putIntWithLongHandle = handles.get(idx++);
415 putIntWithObjectHandle = handles.get(idx++);
416 putOrderedIntWithObjectHandle = handles.get(idx++);
417 putLongWithLongHandle = handles.get(idx++);
418 putLongWithObjectHandle = handles.get(idx++);
419 putObjectWithObjectHandle = handles.get(idx++);
420 addressSizeHandle = handles.get(idx++);
421 storeFenceHandle = handles.get(idx);
422 }
423 }
424 }
425
426 UNSAFE_ALLOCATE_MEMORY_HANDLE = allocateMemoryHandle;
427 UNSAFE_COPY_MEMORY_WITH_LONG_HANDLE = copyMemoryWithLongHandle;
428 UNSAFE_COPY_MEMORY_WITH_OBJECT_HANDLE = copyMemoryWithObjectHandle;
429 UNSAFE_OBJECT_FIELD_OFFSET_HANDLE = objectFieldOffsetHandle;
430 UNSAFE_REALLOCATE_MEMORY_HANDLE = reallocateMemoryHandle;
431 UNSAFE_FREE_MEMORY_HANDLE = freeMemoryHandle;
432 UNSAFE_SET_MEMORY_WITH_LONG_HANDLE = setMemoryWithLongHandle;
433 UNSAFE_SET_MEMORY_WITH_OBJECT_HANDLE = setMemoryWithObjectHandle;
434 UNSAFE_GET_BYTE_WITH_LONG_HANDLE = getByteWithLongHandle;
435 UNSAFE_GET_BYTE_WITH_OBJECT_HANDLE = getByteWithObjectHandle;
436 UNSAFE_GET_CHAR_WITH_OBJECT_HANDLE = getCharWithObjectHandle;
437 UNSAFE_GET_SHORT_WITH_LONG_HANDLE = getShortWithLongHandle;
438 UNSAFE_GET_SHORT_WITH_OBJECT_HANDLE = getShortWithObjectHandle;
439 UNSAFE_GET_INT_WITH_LONG_HANDLE = getIntWithLongHandle;
440 UNSAFE_GET_INT_WITH_OBJECT_HANDLE = getIntWithObjectHandle;
441 UNSAFE_GET_INT_VOLATILE_WITH_OBJECT_HANDLE = getIntVolatileWithObjectHandle;
442 UNSAFE_GET_LONG_WITH_LONG_HANDLE = getLongWithLongHandle;
443 UNSAFE_GET_LONG_WITH_OBJECT_HANDLE = getLongWithObjectHandle;
444 UNSAFE_GET_OBJECT_WITH_OBJECT_HANDLE = getObjectWithObjectHandle;
445 UNSAFE_PUT_BYTE_WITH_LONG_HANDLE = putByteWithLongHandle;
446 UNSAFE_PUT_BYTE_WITH_OBJECT_HANDLE = putByteWithObjectHandle;
447 UNSAFE_PUT_SHORT_WITH_LONG_HANDLE = putShortWithLongHandle;
448 UNSAFE_PUT_SHORT_WITH_OBJECT_HANDLE = putShortWithObjectHandle;
449 UNSAFE_PUT_INT_WITH_LONG_HANDLE = putIntWithLongHandle;
450 UNSAFE_PUT_INT_WITH_OBJECT_HANDLE = putIntWithObjectHandle;
451 UNSAFE_PUT_ORDERED_INT_WITH_OBJECT_HANDLE = putOrderedIntWithObjectHandle;
452 UNSAFE_PUT_LONG_WITH_LONG_HANDLE = putLongWithLongHandle;
453 UNSAFE_PUT_LONG_WITH_OBJECT_HANDLE = putLongWithObjectHandle;
454 UNSAFE_PUT_OBJECT_WITH_OBJECT_HANDLE = putObjectWithObjectHandle;
455 UNSAFE_ADDRESS_SIZE_HANDLE = addressSizeHandle;
456 UNSAFE_STORE_FENCE_HANDLE = storeFenceHandle;
457 UNSAFE_ARRAY_BASE_OFFSET_HANDLE = arrayBaseOffsetHandle;
458 UNSAFE_ARRAY_INDEX_SCALE_HANDLE = arrayIndexScaleHandle;
459 UNSAFE_STATIC_FIELD_OFFSET_HANDLE = staticFieldOffsetHandle;
460 UNSAFE_STATIC_FIELD_BASE_HANDLE = staticFieldBaseHandle;
461 UNSAFE_GET_BOOLEAN_WITH_OBJECT_HANDLE = getBooleanWithObjectHandle;
462 UNSAFE_UNAVAILABILITY_CAUSE = unsafeUnavailabilityCause;
463 UNSAFE = unsafe;
464 }
465
466 static boolean isExplicitNoUnsafe() {
467 return EXPLICIT_NO_UNSAFE_CAUSE != null;
468 }
469
470 private static Throwable explicitNoUnsafeCause0() {
471 boolean noUnsafe = SystemPropertyUtil.getBoolean("io.netty.noUnsafe", false);
472 logger.debug("-Dio.netty.noUnsafe: {}", noUnsafe);
473
474
475 String unsafeMemoryAccess = SystemPropertyUtil.get("sun.misc.unsafe.memory.access", "<unspecified>");
476 if (!("allow".equals(unsafeMemoryAccess) || "<unspecified>".equals(unsafeMemoryAccess))) {
477 logger.debug("--sun-misc-unsafe-memory-access={}", unsafeMemoryAccess);
478 noUnsafe = true;
479 }
480
481 if (noUnsafe) {
482 logger.debug("{}: unavailable (io.netty.noUnsafe)", SUN_MISC_UNSAFE_CLASS_NAME);
483 return new UnsupportedOperationException("sun.misc.Unsafe: unavailable (io.netty.noUnsafe)");
484 }
485
486
487 String unsafePropName;
488 if (SystemPropertyUtil.contains("io.netty.tryUnsafe")) {
489 unsafePropName = "io.netty.tryUnsafe";
490 } else {
491 unsafePropName = "org.jboss.netty.tryUnsafe";
492 }
493
494 if (!SystemPropertyUtil.getBoolean(unsafePropName, true)) {
495 String msg = "{}: unavailable ({})";
496 logger.debug(msg, SUN_MISC_UNSAFE_CLASS_NAME, unsafePropName);
497 return new UnsupportedOperationException(msg);
498 }
499
500 return null;
501 }
502
503 static int arrayIndexScale(Class<?> arrayClass) {
504 try {
505 return (int) UNSAFE_ARRAY_INDEX_SCALE_HANDLE.invokeExact(arrayClass);
506 } catch (Throwable cause) {
507 rethrowIfPossible(cause);
508 throw new IllegalStateException(cause);
509 }
510 }
511
512 static int arrayBaseOffset(Class<?> arrayClass) {
513 try {
514 return (int) UNSAFE_ARRAY_BASE_OFFSET_HANDLE.invokeExact(arrayClass);
515 } catch (Throwable cause) {
516 rethrowIfPossible(cause);
517 throw new IllegalStateException(cause);
518 }
519 }
520
521 static void storeFence() {
522 try {
523 UNSAFE_STORE_FENCE_HANDLE.invokeExact();
524 } catch (Throwable cause) {
525 rethrowIfPossible(cause);
526 throw new IllegalStateException(cause);
527 }
528 }
529
530 static long objectFieldOffset(Field field) {
531 try {
532 return (long) UNSAFE_OBJECT_FIELD_OFFSET_HANDLE.invokeExact(field);
533 } catch (Throwable cause) {
534 rethrowIfPossible(cause);
535 throw new IllegalStateException(cause);
536 }
537 }
538
539 static long staticFieldOffset(Field f) {
540 try {
541 return (long) UNSAFE_STATIC_FIELD_OFFSET_HANDLE.invokeExact(f);
542 } catch (Throwable cause) {
543 rethrowIfPossible(cause);
544 throw new IllegalStateException(cause);
545 }
546 }
547
548 static Object staticFieldBase(Field f) {
549 try {
550 return UNSAFE_STATIC_FIELD_BASE_HANDLE.invokeExact(f);
551 } catch (Throwable cause) {
552 rethrowIfPossible(cause);
553 throw new IllegalStateException(cause);
554 }
555 }
556
557 static boolean getBoolean(Object o, long offset) {
558 try {
559 return (boolean) UNSAFE_GET_BOOLEAN_WITH_OBJECT_HANDLE.invokeExact(o, offset);
560 } catch (Throwable cause) {
561 rethrowIfPossible(cause);
562 throw new IllegalStateException(cause);
563 }
564 }
565
566 static Object getObject(Object object, long fieldOffset) {
567 try {
568 return (Object) UNSAFE_GET_OBJECT_WITH_OBJECT_HANDLE.invokeExact(object, fieldOffset);
569 } catch (Throwable cause) {
570 rethrowIfPossible(cause);
571 throw new IllegalStateException(cause);
572 }
573 }
574
575 static long getLong(Object object, long fieldOffset) {
576 try {
577 return (long) UNSAFE_GET_LONG_WITH_OBJECT_HANDLE.invokeExact(object, fieldOffset);
578 } catch (Throwable cause) {
579 rethrowIfPossible(cause);
580 throw new IllegalStateException(cause);
581 }
582 }
583
584 static byte getByte(long address) {
585 try {
586 return (byte) UNSAFE_GET_BYTE_WITH_LONG_HANDLE.invokeExact(address);
587 } catch (Throwable cause) {
588 rethrowIfPossible(cause);
589 throw new IllegalStateException(cause);
590 }
591 }
592
593 static short getShort(long address) {
594 try {
595 return (short) UNSAFE_GET_SHORT_WITH_LONG_HANDLE.invokeExact(address);
596 } catch (Throwable cause) {
597 rethrowIfPossible(cause);
598 throw new IllegalStateException(cause);
599 }
600 }
601
602 static int getInt(long address) {
603 try {
604 return (int) UNSAFE_GET_INT_WITH_LONG_HANDLE.invokeExact(address);
605 } catch (Throwable cause) {
606 rethrowIfPossible(cause);
607 throw new IllegalStateException(cause);
608 }
609 }
610
611 static long getLong(long address) {
612 try {
613 return (long) UNSAFE_GET_LONG_WITH_LONG_HANDLE.invokeExact(address);
614 } catch (Throwable cause) {
615 rethrowIfPossible(cause);
616 throw new IllegalStateException(cause);
617 }
618 }
619
620 static byte getByte(Object o, long offset) {
621 try {
622 return (byte) UNSAFE_GET_BYTE_WITH_OBJECT_HANDLE.invokeExact(o, offset);
623 } catch (Throwable cause) {
624 rethrowIfPossible(cause);
625 throw new IllegalStateException(cause);
626 }
627 }
628
629 static short getShort(Object o, long offset) {
630 try {
631 return (short) UNSAFE_GET_SHORT_WITH_OBJECT_HANDLE.invokeExact(o, offset);
632 } catch (Throwable cause) {
633 rethrowIfPossible(cause);
634 throw new IllegalStateException(cause);
635 }
636 }
637
638 static char getChar(Object o, long offset) {
639 try {
640 return (char) UNSAFE_GET_CHAR_WITH_OBJECT_HANDLE.invokeExact(o, offset);
641 } catch (Throwable cause) {
642 rethrowIfPossible(cause);
643 throw new IllegalStateException(cause);
644 }
645 }
646
647 static int getInt(Object o, long offset) {
648 try {
649 return (int) UNSAFE_GET_INT_WITH_OBJECT_HANDLE.invokeExact(o, offset);
650 } catch (Throwable cause) {
651 rethrowIfPossible(cause);
652 throw new IllegalStateException(cause);
653 }
654 }
655
656 static int getIntVolatile(Object o, long address) {
657 try {
658 return (int) UNSAFE_GET_INT_VOLATILE_WITH_OBJECT_HANDLE.invokeExact(o, address);
659 } catch (Throwable cause) {
660 rethrowIfPossible(cause);
661 throw new IllegalStateException(cause);
662 }
663 }
664
665 static void putIntOrdered(Object o, long address, int newValue) {
666 try {
667 UNSAFE_PUT_ORDERED_INT_WITH_OBJECT_HANDLE.invokeExact(o, address, newValue);
668 } catch (Throwable cause) {
669 rethrowIfPossible(cause);
670 throw new IllegalStateException(cause);
671 }
672 }
673
674 static void putByte(long address, byte value) {
675 try {
676 UNSAFE_PUT_BYTE_WITH_LONG_HANDLE.invokeExact(address, value);
677 } catch (Throwable cause) {
678 rethrowIfPossible(cause);
679 throw new IllegalStateException(cause);
680 }
681 }
682
683 static void putShort(long address, short value) {
684 try {
685 UNSAFE_PUT_SHORT_WITH_LONG_HANDLE.invokeExact(address, value);
686 } catch (Throwable cause) {
687 rethrowIfPossible(cause);
688 throw new IllegalStateException(cause);
689 }
690 }
691
692 static void putInt(long address, int value) {
693 try {
694 UNSAFE_PUT_INT_WITH_LONG_HANDLE.invokeExact(address, value);
695 } catch (Throwable cause) {
696 rethrowIfPossible(cause);
697 throw new IllegalStateException(cause);
698 }
699 }
700
701 static void putLong(long address, long value) {
702 try {
703 UNSAFE_PUT_LONG_WITH_LONG_HANDLE.invokeExact(address, value);
704 } catch (Throwable cause) {
705 rethrowIfPossible(cause);
706 throw new IllegalStateException(cause);
707 }
708 }
709
710 static void putByte(Object o, long offset, byte value) {
711 try {
712 UNSAFE_PUT_BYTE_WITH_OBJECT_HANDLE.invokeExact(o, offset, value);
713 } catch (Throwable cause) {
714 rethrowIfPossible(cause);
715 throw new IllegalStateException(cause);
716 }
717 }
718
719 static void putShort(Object o, long offset, short value) {
720 try {
721 UNSAFE_PUT_SHORT_WITH_OBJECT_HANDLE.invokeExact(o, offset, value);
722 } catch (Throwable cause) {
723 rethrowIfPossible(cause);
724 throw new IllegalStateException(cause);
725 }
726 }
727
728 static void putInt(Object o, long offset, int value) {
729 try {
730 UNSAFE_PUT_INT_WITH_OBJECT_HANDLE.invokeExact(o, offset, value);
731 } catch (Throwable cause) {
732 rethrowIfPossible(cause);
733 throw new IllegalStateException(cause);
734 }
735 }
736
737 static void putLong(Object o, long offset, long value) {
738 try {
739 UNSAFE_PUT_LONG_WITH_OBJECT_HANDLE.invokeExact(o, offset, value);
740 } catch (Throwable cause) {
741 rethrowIfPossible(cause);
742 throw new IllegalStateException(cause);
743 }
744 }
745
746 static void putObject(Object o, long offset, Object value) {
747 try {
748 UNSAFE_PUT_OBJECT_WITH_OBJECT_HANDLE.invokeExact(o, offset, value);
749 } catch (Throwable cause) {
750 rethrowIfPossible(cause);
751 throw new IllegalStateException(cause);
752 }
753 }
754
755 static void copyMemory(Object srcBase, long srcOffset,
756 Object destBase, long destOffset,
757 long bytes) {
758 try {
759 UNSAFE_COPY_MEMORY_WITH_OBJECT_HANDLE.invokeExact(srcBase, srcOffset, destBase, destOffset, bytes);
760 } catch (Throwable cause) {
761 rethrowIfPossible(cause);
762 throw new IllegalStateException(cause);
763 }
764 }
765
766 static void copyMemory(long srcAddress, long destAddress, long bytes) {
767 try {
768 UNSAFE_COPY_MEMORY_WITH_LONG_HANDLE.invokeExact(srcAddress, destAddress, bytes);
769 } catch (Throwable cause) {
770 rethrowIfPossible(cause);
771 throw new IllegalStateException(cause);
772 }
773 }
774
775 static void setMemory(long address, long bytes, byte value) {
776 try {
777 UNSAFE_SET_MEMORY_WITH_LONG_HANDLE.invokeExact(address, bytes, value);
778 } catch (Throwable cause) {
779 rethrowIfPossible(cause);
780 throw new IllegalStateException(cause);
781 }
782 }
783
784 static void setMemory(Object o, long offset, long bytes, byte value) {
785 try {
786 UNSAFE_SET_MEMORY_WITH_OBJECT_HANDLE.invokeExact(o, offset, bytes, value);
787 } catch (Throwable cause) {
788 rethrowIfPossible(cause);
789 throw new IllegalStateException(cause);
790 }
791 }
792
793 static int addressSize() {
794 try {
795 return (int) UNSAFE_ADDRESS_SIZE_HANDLE.invokeExact();
796 } catch (Throwable cause) {
797 rethrowIfPossible(cause);
798 throw new IllegalStateException(cause);
799 }
800 }
801
802 static long allocateMemory(long size) {
803 try {
804 return (long) UNSAFE_ALLOCATE_MEMORY_HANDLE.invokeExact(size);
805 } catch (Throwable cause) {
806 rethrowIfPossible(cause);
807 throw new IllegalStateException(cause);
808 }
809 }
810
811 static void freeMemory(long address) {
812 try {
813 UNSAFE_FREE_MEMORY_HANDLE.invokeExact(address);
814 } catch (Throwable cause) {
815 rethrowIfPossible(cause);
816 throw new IllegalStateException(cause);
817 }
818 }
819
820 static long reallocateMemory(long address, long newSize) {
821 try {
822 return (long) UNSAFE_REALLOCATE_MEMORY_HANDLE.invokeExact(address, newSize);
823 } catch (Throwable cause) {
824 rethrowIfPossible(cause);
825 throw new IllegalStateException(cause);
826 }
827 }
828
829 private static void rethrowIfPossible(Throwable cause) {
830 if (cause instanceof Error) {
831 throw (Error) cause;
832 }
833 if (cause instanceof RuntimeException) {
834 throw (RuntimeException) cause;
835 }
836 }
837
838 static boolean isAvailabile() {
839 return UNSAFE_UNAVAILABILITY_CAUSE == null && UNSAFE != null;
840 }
841
842 static Throwable unavailabilityCause() {
843 return UNSAFE_UNAVAILABILITY_CAUSE;
844 }
845
846 private SunMiscUnsafeAccess() { }
847 }