• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 package com.google.protobuf;
32 
33 import java.lang.reflect.Field;
34 import java.nio.Buffer;
35 import java.nio.ByteBuffer;
36 import java.nio.ByteOrder;
37 import java.security.AccessController;
38 import java.security.PrivilegedExceptionAction;
39 import java.util.logging.Level;
40 import java.util.logging.Logger;
41 
42 /** Utility class for working with unsafe operations. */
43 final class UnsafeUtil {
44   private static final Logger logger = Logger.getLogger(UnsafeUtil.class.getName());
45   private static final sun.misc.Unsafe UNSAFE = getUnsafe();
46   private static final MemoryAccessor MEMORY_ACCESSOR = getMemoryAccessor();
47   private static final boolean HAS_UNSAFE_BYTEBUFFER_OPERATIONS =
48       supportsUnsafeByteBufferOperations();
49   private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = supportsUnsafeArrayOperations();
50 
51   static final long BYTE_ARRAY_BASE_OFFSET = arrayBaseOffset(byte[].class);
52   // Micro-optimization: we can assume a scale of 1 and skip the multiply
53   // private static final long BYTE_ARRAY_INDEX_SCALE = 1;
54 
55   private static final long BOOLEAN_ARRAY_BASE_OFFSET = arrayBaseOffset(boolean[].class);
56   private static final long BOOLEAN_ARRAY_INDEX_SCALE = arrayIndexScale(boolean[].class);
57 
58   private static final long INT_ARRAY_BASE_OFFSET = arrayBaseOffset(int[].class);
59   private static final long INT_ARRAY_INDEX_SCALE = arrayIndexScale(int[].class);
60 
61   private static final long LONG_ARRAY_BASE_OFFSET = arrayBaseOffset(long[].class);
62   private static final long LONG_ARRAY_INDEX_SCALE = arrayIndexScale(long[].class);
63 
64   private static final long FLOAT_ARRAY_BASE_OFFSET = arrayBaseOffset(float[].class);
65   private static final long FLOAT_ARRAY_INDEX_SCALE = arrayIndexScale(float[].class);
66 
67   private static final long DOUBLE_ARRAY_BASE_OFFSET = arrayBaseOffset(double[].class);
68   private static final long DOUBLE_ARRAY_INDEX_SCALE = arrayIndexScale(double[].class);
69 
70   private static final long OBJECT_ARRAY_BASE_OFFSET = arrayBaseOffset(Object[].class);
71   private static final long OBJECT_ARRAY_INDEX_SCALE = arrayIndexScale(Object[].class);
72 
73   private static final long BUFFER_ADDRESS_OFFSET = fieldOffset(bufferAddressField());
74 
75   private static final int STRIDE = 8;
76   private static final int STRIDE_ALIGNMENT_MASK = STRIDE - 1;
77   private static final int BYTE_ARRAY_ALIGNMENT =
78       (int) (BYTE_ARRAY_BASE_OFFSET & STRIDE_ALIGNMENT_MASK);
79 
80   static final boolean IS_BIG_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
81 
UnsafeUtil()82   private UnsafeUtil() {}
83 
hasUnsafeArrayOperations()84   static boolean hasUnsafeArrayOperations() {
85     return HAS_UNSAFE_ARRAY_OPERATIONS;
86   }
87 
hasUnsafeByteBufferOperations()88   static boolean hasUnsafeByteBufferOperations() {
89     return HAS_UNSAFE_BYTEBUFFER_OPERATIONS;
90   }
91 
92 
93   @SuppressWarnings("unchecked") // safe by method contract
allocateInstance(Class<T> clazz)94   static <T> T allocateInstance(Class<T> clazz) {
95     try {
96       return (T) UNSAFE.allocateInstance(clazz);
97     } catch (InstantiationException e) {
98       throw new IllegalStateException(e);
99     }
100   }
101 
objectFieldOffset(Field field)102   static long objectFieldOffset(Field field) {
103     return MEMORY_ACCESSOR.objectFieldOffset(field);
104   }
105 
arrayBaseOffset(Class<?> clazz)106   private static int arrayBaseOffset(Class<?> clazz) {
107     return HAS_UNSAFE_ARRAY_OPERATIONS ? MEMORY_ACCESSOR.arrayBaseOffset(clazz) : -1;
108   }
109 
arrayIndexScale(Class<?> clazz)110   private static int arrayIndexScale(Class<?> clazz) {
111     return HAS_UNSAFE_ARRAY_OPERATIONS ? MEMORY_ACCESSOR.arrayIndexScale(clazz) : -1;
112   }
113 
getByte(Object target, long offset)114   static byte getByte(Object target, long offset) {
115     return MEMORY_ACCESSOR.getByte(target, offset);
116   }
117 
putByte(Object target, long offset, byte value)118   static void putByte(Object target, long offset, byte value) {
119     MEMORY_ACCESSOR.putByte(target, offset, value);
120   }
121 
getInt(Object target, long offset)122   static int getInt(Object target, long offset) {
123     return MEMORY_ACCESSOR.getInt(target, offset);
124   }
125 
putInt(Object target, long offset, int value)126   static void putInt(Object target, long offset, int value) {
127     MEMORY_ACCESSOR.putInt(target, offset, value);
128   }
129 
getLong(Object target, long offset)130   static long getLong(Object target, long offset) {
131     return MEMORY_ACCESSOR.getLong(target, offset);
132   }
133 
putLong(Object target, long offset, long value)134   static void putLong(Object target, long offset, long value) {
135     MEMORY_ACCESSOR.putLong(target, offset, value);
136   }
137 
getBoolean(Object target, long offset)138   static boolean getBoolean(Object target, long offset) {
139     return MEMORY_ACCESSOR.getBoolean(target, offset);
140   }
141 
putBoolean(Object target, long offset, boolean value)142   static void putBoolean(Object target, long offset, boolean value) {
143     MEMORY_ACCESSOR.putBoolean(target, offset, value);
144   }
145 
getFloat(Object target, long offset)146   static float getFloat(Object target, long offset) {
147     return MEMORY_ACCESSOR.getFloat(target, offset);
148   }
149 
putFloat(Object target, long offset, float value)150   static void putFloat(Object target, long offset, float value) {
151     MEMORY_ACCESSOR.putFloat(target, offset, value);
152   }
153 
getDouble(Object target, long offset)154   static double getDouble(Object target, long offset) {
155     return MEMORY_ACCESSOR.getDouble(target, offset);
156   }
157 
putDouble(Object target, long offset, double value)158   static void putDouble(Object target, long offset, double value) {
159     MEMORY_ACCESSOR.putDouble(target, offset, value);
160   }
161 
getObject(Object target, long offset)162   static Object getObject(Object target, long offset) {
163     return MEMORY_ACCESSOR.getObject(target, offset);
164   }
165 
putObject(Object target, long offset, Object value)166   static void putObject(Object target, long offset, Object value) {
167     MEMORY_ACCESSOR.putObject(target, offset, value);
168   }
169 
getByte(byte[] target, long index)170   static byte getByte(byte[] target, long index) {
171     return MEMORY_ACCESSOR.getByte(target, BYTE_ARRAY_BASE_OFFSET + index);
172   }
173 
putByte(byte[] target, long index, byte value)174   static void putByte(byte[] target, long index, byte value) {
175     MEMORY_ACCESSOR.putByte(target, BYTE_ARRAY_BASE_OFFSET + index, value);
176   }
177 
getInt(int[] target, long index)178   static int getInt(int[] target, long index) {
179     return MEMORY_ACCESSOR.getInt(target, INT_ARRAY_BASE_OFFSET + (index * INT_ARRAY_INDEX_SCALE));
180   }
181 
putInt(int[] target, long index, int value)182   static void putInt(int[] target, long index, int value) {
183     MEMORY_ACCESSOR.putInt(target, INT_ARRAY_BASE_OFFSET + (index * INT_ARRAY_INDEX_SCALE), value);
184   }
185 
getLong(long[] target, long index)186   static long getLong(long[] target, long index) {
187     return MEMORY_ACCESSOR.getLong(
188         target, LONG_ARRAY_BASE_OFFSET + (index * LONG_ARRAY_INDEX_SCALE));
189   }
190 
putLong(long[] target, long index, long value)191   static void putLong(long[] target, long index, long value) {
192     MEMORY_ACCESSOR.putLong(
193         target, LONG_ARRAY_BASE_OFFSET + (index * LONG_ARRAY_INDEX_SCALE), value);
194   }
195 
getBoolean(boolean[] target, long index)196   static boolean getBoolean(boolean[] target, long index) {
197     return MEMORY_ACCESSOR.getBoolean(
198         target, BOOLEAN_ARRAY_BASE_OFFSET + (index * BOOLEAN_ARRAY_INDEX_SCALE));
199   }
200 
putBoolean(boolean[] target, long index, boolean value)201   static void putBoolean(boolean[] target, long index, boolean value) {
202     MEMORY_ACCESSOR.putBoolean(
203         target, BOOLEAN_ARRAY_BASE_OFFSET + (index * BOOLEAN_ARRAY_INDEX_SCALE), value);
204   }
205 
getFloat(float[] target, long index)206   static float getFloat(float[] target, long index) {
207     return MEMORY_ACCESSOR.getFloat(
208         target, FLOAT_ARRAY_BASE_OFFSET + (index * FLOAT_ARRAY_INDEX_SCALE));
209   }
210 
putFloat(float[] target, long index, float value)211   static void putFloat(float[] target, long index, float value) {
212     MEMORY_ACCESSOR.putFloat(
213         target, FLOAT_ARRAY_BASE_OFFSET + (index * FLOAT_ARRAY_INDEX_SCALE), value);
214   }
215 
getDouble(double[] target, long index)216   static double getDouble(double[] target, long index) {
217     return MEMORY_ACCESSOR.getDouble(
218         target, DOUBLE_ARRAY_BASE_OFFSET + (index * DOUBLE_ARRAY_INDEX_SCALE));
219   }
220 
putDouble(double[] target, long index, double value)221   static void putDouble(double[] target, long index, double value) {
222     MEMORY_ACCESSOR.putDouble(
223         target, DOUBLE_ARRAY_BASE_OFFSET + (index * DOUBLE_ARRAY_INDEX_SCALE), value);
224   }
225 
getObject(Object[] target, long index)226   static Object getObject(Object[] target, long index) {
227     return MEMORY_ACCESSOR.getObject(
228         target, OBJECT_ARRAY_BASE_OFFSET + (index * OBJECT_ARRAY_INDEX_SCALE));
229   }
230 
putObject(Object[] target, long index, Object value)231   static void putObject(Object[] target, long index, Object value) {
232     MEMORY_ACCESSOR.putObject(
233         target, OBJECT_ARRAY_BASE_OFFSET + (index * OBJECT_ARRAY_INDEX_SCALE), value);
234   }
235 
copyMemory(byte[] src, long srcIndex, long targetOffset, long length)236   static void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
237     MEMORY_ACCESSOR.copyMemory(src, srcIndex, targetOffset, length);
238   }
239 
copyMemory(long srcOffset, byte[] target, long targetIndex, long length)240   static void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
241     MEMORY_ACCESSOR.copyMemory(srcOffset, target, targetIndex, length);
242   }
243 
copyMemory(byte[] src, long srcIndex, byte[] target, long targetIndex, long length)244   static void copyMemory(byte[] src, long srcIndex, byte[] target, long targetIndex, long length) {
245     System.arraycopy(src, (int) srcIndex, target, (int) targetIndex, (int) length);
246   }
247 
getByte(long address)248   static byte getByte(long address) {
249     return MEMORY_ACCESSOR.getByte(address);
250   }
251 
putByte(long address, byte value)252   static void putByte(long address, byte value) {
253     MEMORY_ACCESSOR.putByte(address, value);
254   }
255 
getInt(long address)256   static int getInt(long address) {
257     return MEMORY_ACCESSOR.getInt(address);
258   }
259 
putInt(long address, int value)260   static void putInt(long address, int value) {
261     MEMORY_ACCESSOR.putInt(address, value);
262   }
263 
getLong(long address)264   static long getLong(long address) {
265     return MEMORY_ACCESSOR.getLong(address);
266   }
267 
putLong(long address, long value)268   static void putLong(long address, long value) {
269     MEMORY_ACCESSOR.putLong(address, value);
270   }
271 
272   /** Gets the offset of the {@code address} field of the given direct {@link ByteBuffer}. */
addressOffset(ByteBuffer buffer)273   static long addressOffset(ByteBuffer buffer) {
274     return MEMORY_ACCESSOR.getLong(buffer, BUFFER_ADDRESS_OFFSET);
275   }
276 
getStaticObject(Field field)277   static Object getStaticObject(Field field) {
278     return MEMORY_ACCESSOR.getStaticObject(field);
279   }
280 
281   /**
282    * Gets the {@code sun.misc.Unsafe} instance, or {@code null} if not available on this platform.
283    */
getUnsafe()284   static sun.misc.Unsafe getUnsafe() {
285     sun.misc.Unsafe unsafe = null;
286     try {
287       unsafe =
288           AccessController.doPrivileged(
289               new PrivilegedExceptionAction<sun.misc.Unsafe>() {
290                 @Override
291                 public sun.misc.Unsafe run() throws Exception {
292                   Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
293 
294                   for (Field f : k.getDeclaredFields()) {
295                     f.setAccessible(true);
296                     Object x = f.get(null);
297                     if (k.isInstance(x)) {
298                       return k.cast(x);
299                     }
300                   }
301                   // The sun.misc.Unsafe field does not exist.
302                   return null;
303                 }
304               });
305     } catch (Throwable e) {
306       // Catching Throwable here due to the fact that Google AppEngine raises NoClassDefFoundError
307       // for Unsafe.
308     }
309     return unsafe;
310   }
311 
312   /** Get a {@link MemoryAccessor} appropriate for the platform, or null if not supported. */
getMemoryAccessor()313   private static MemoryAccessor getMemoryAccessor() {
314     if (UNSAFE == null) {
315       return null;
316     }
317     return new JvmMemoryAccessor(UNSAFE);
318   }
319 
320   /** Indicates whether or not unsafe array operations are supported on this platform. */
supportsUnsafeArrayOperations()321   private static boolean supportsUnsafeArrayOperations() {
322     if (UNSAFE == null) {
323       return false;
324     }
325     try {
326       Class<?> clazz = UNSAFE.getClass();
327       clazz.getMethod("objectFieldOffset", Field.class);
328       clazz.getMethod("arrayBaseOffset", Class.class);
329       clazz.getMethod("arrayIndexScale", Class.class);
330       clazz.getMethod("getInt", Object.class, long.class);
331       clazz.getMethod("putInt", Object.class, long.class, int.class);
332       clazz.getMethod("getLong", Object.class, long.class);
333       clazz.getMethod("putLong", Object.class, long.class, long.class);
334       clazz.getMethod("getObject", Object.class, long.class);
335       clazz.getMethod("putObject", Object.class, long.class, Object.class);
336       clazz.getMethod("getByte", Object.class, long.class);
337       clazz.getMethod("putByte", Object.class, long.class, byte.class);
338       clazz.getMethod("getBoolean", Object.class, long.class);
339       clazz.getMethod("putBoolean", Object.class, long.class, boolean.class);
340       clazz.getMethod("getFloat", Object.class, long.class);
341       clazz.getMethod("putFloat", Object.class, long.class, float.class);
342       clazz.getMethod("getDouble", Object.class, long.class);
343       clazz.getMethod("putDouble", Object.class, long.class, double.class);
344 
345       return true;
346     } catch (Throwable e) {
347       logger.log(
348           Level.WARNING,
349           "platform method missing - proto runtime falling back to safer methods: " + e);
350     }
351     return false;
352   }
353 
supportsUnsafeByteBufferOperations()354   private static boolean supportsUnsafeByteBufferOperations() {
355     if (UNSAFE == null) {
356       return false;
357     }
358     try {
359       Class<?> clazz = UNSAFE.getClass();
360       // Methods for getting direct buffer address.
361       clazz.getMethod("objectFieldOffset", Field.class);
362       clazz.getMethod("getLong", Object.class, long.class);
363 
364       if (bufferAddressField() == null) {
365         return false;
366       }
367 
368       clazz.getMethod("getByte", long.class);
369       clazz.getMethod("putByte", long.class, byte.class);
370       clazz.getMethod("getInt", long.class);
371       clazz.getMethod("putInt", long.class, int.class);
372       clazz.getMethod("getLong", long.class);
373       clazz.getMethod("putLong", long.class, long.class);
374       clazz.getMethod("copyMemory", long.class, long.class, long.class);
375       clazz.getMethod("copyMemory", Object.class, long.class, Object.class, long.class, long.class);
376       return true;
377     } catch (Throwable e) {
378       logger.log(
379           Level.WARNING,
380           "platform method missing - proto runtime falling back to safer methods: " + e);
381     }
382     return false;
383   }
384 
385 
386   /** Finds the address field within a direct {@link Buffer}. */
bufferAddressField()387   private static Field bufferAddressField() {
388     Field field = field(Buffer.class, "address");
389     return field != null && field.getType() == long.class ? field : null;
390   }
391 
392   /**
393    * Returns the index of the first byte where left and right differ, in the range [0, 8]. If {@code
394    * left == right}, the result will be 8, otherwise less than 8.
395    *
396    * <p>This counts from the *first* byte, which may be the most or least significant byte depending
397    * on the system endianness.
398    */
firstDifferingByteIndexNativeEndian(long left, long right)399   private static int firstDifferingByteIndexNativeEndian(long left, long right) {
400     int n =
401         IS_BIG_ENDIAN
402             ? Long.numberOfLeadingZeros(left ^ right)
403             : Long.numberOfTrailingZeros(left ^ right);
404     return n >> 3;
405   }
406 
407   /**
408    * Returns the lowest {@code index} such that {@code 0 <= index < length} and {@code left[leftOff
409    * + index] != right[rightOff + index]}. If no such value exists -- if {@code left} and {@code
410    * right} match up to {@code length} bytes from their respective offsets -- returns -1.
411    *
412    * <p>{@code leftOff + length} must be less than or equal to {@code left.length}, and the same for
413    * {@code right}.
414    */
mismatch(byte[] left, int leftOff, byte[] right, int rightOff, int length)415   static int mismatch(byte[] left, int leftOff, byte[] right, int rightOff, int length) {
416     if (leftOff < 0
417         || rightOff < 0
418         || length < 0
419         || leftOff + length > left.length
420         || rightOff + length > right.length) {
421       throw new IndexOutOfBoundsException();
422     }
423 
424     int index = 0;
425     if (HAS_UNSAFE_ARRAY_OPERATIONS) {
426       int leftAlignment = (BYTE_ARRAY_ALIGNMENT + leftOff) & STRIDE_ALIGNMENT_MASK;
427 
428       // Most CPUs handle getting chunks of bytes better on addresses that are a multiple of 4
429       // or 8.
430       // We walk one byte at a time until the left address, at least, is a multiple of 8.
431       // If the right address is, too, so much the better.
432       for (;
433           index < length && (leftAlignment & STRIDE_ALIGNMENT_MASK) != 0;
434           index++, leftAlignment++) {
435         if (left[leftOff + index] != right[rightOff + index]) {
436           return index;
437         }
438       }
439 
440       // Stride!  Grab eight bytes at a time from left and right and check them for equality.
441 
442       int strideLength = ((length - index) & ~STRIDE_ALIGNMENT_MASK) + index;
443       // strideLength is the point where we want to stop striding: it differs from index by
444       // a multiple of STRIDE, and it's the largest such number <= length.
445 
446       for (; index < strideLength; index += STRIDE) {
447         long leftLongWord = getLong(left, BYTE_ARRAY_BASE_OFFSET + leftOff + index);
448         long rightLongWord = getLong(right, BYTE_ARRAY_BASE_OFFSET + rightOff + index);
449         if (leftLongWord != rightLongWord) {
450           // one of these eight bytes differ!  use a helper to find out which one
451           return index + firstDifferingByteIndexNativeEndian(leftLongWord, rightLongWord);
452         }
453       }
454     }
455 
456     // If we were able to stride, there are at most STRIDE - 1 bytes left to compare.
457     // If we weren't, then this loop covers the whole thing.
458     for (; index < length; index++) {
459       if (left[leftOff + index] != right[rightOff + index]) {
460         return index;
461       }
462     }
463     return -1;
464   }
465 
466   /**
467    * Returns the offset of the provided field, or {@code -1} if {@code sun.misc.Unsafe} is not
468    * available.
469    */
fieldOffset(Field field)470   private static long fieldOffset(Field field) {
471     return field == null || MEMORY_ACCESSOR == null ? -1 : MEMORY_ACCESSOR.objectFieldOffset(field);
472   }
473 
474   /**
475    * Gets the field with the given name within the class, or {@code null} if not found.
476    */
field(Class<?> clazz, String fieldName)477   private static Field field(Class<?> clazz, String fieldName) {
478     Field field;
479     try {
480       field = clazz.getDeclaredField(fieldName);
481     } catch (Throwable t) {
482       // Failed to access the fields.
483       field = null;
484     }
485     return field;
486   }
487 
488   private abstract static class MemoryAccessor {
489 
490     sun.misc.Unsafe unsafe;
491 
MemoryAccessor(sun.misc.Unsafe unsafe)492     MemoryAccessor(sun.misc.Unsafe unsafe) {
493       this.unsafe = unsafe;
494     }
495 
objectFieldOffset(Field field)496     public final long objectFieldOffset(Field field) {
497       return unsafe.objectFieldOffset(field);
498     }
499 
getByte(Object target, long offset)500     public abstract byte getByte(Object target, long offset);
501 
putByte(Object target, long offset, byte value)502     public abstract void putByte(Object target, long offset, byte value);
503 
getInt(Object target, long offset)504     public final int getInt(Object target, long offset) {
505       return unsafe.getInt(target, offset);
506     }
507 
putInt(Object target, long offset, int value)508     public final void putInt(Object target, long offset, int value) {
509       unsafe.putInt(target, offset, value);
510     }
511 
getLong(Object target, long offset)512     public final long getLong(Object target, long offset) {
513       return unsafe.getLong(target, offset);
514     }
515 
putLong(Object target, long offset, long value)516     public final void putLong(Object target, long offset, long value) {
517       unsafe.putLong(target, offset, value);
518     }
519 
getBoolean(Object target, long offset)520     public abstract boolean getBoolean(Object target, long offset);
521 
putBoolean(Object target, long offset, boolean value)522     public abstract void putBoolean(Object target, long offset, boolean value);
523 
getFloat(Object target, long offset)524     public abstract float getFloat(Object target, long offset);
525 
putFloat(Object target, long offset, float value)526     public abstract void putFloat(Object target, long offset, float value);
527 
getDouble(Object target, long offset)528     public abstract double getDouble(Object target, long offset);
529 
putDouble(Object target, long offset, double value)530     public abstract void putDouble(Object target, long offset, double value);
531 
getObject(Object target, long offset)532     public final Object getObject(Object target, long offset) {
533       return unsafe.getObject(target, offset);
534     }
535 
putObject(Object target, long offset, Object value)536     public final void putObject(Object target, long offset, Object value) {
537       unsafe.putObject(target, offset, value);
538     }
539 
arrayBaseOffset(Class<?> clazz)540     public final int arrayBaseOffset(Class<?> clazz) {
541       return unsafe.arrayBaseOffset(clazz);
542     }
543 
arrayIndexScale(Class<?> clazz)544     public final int arrayIndexScale(Class<?> clazz) {
545       return unsafe.arrayIndexScale(clazz);
546     }
547 
getByte(long address)548     public abstract byte getByte(long address);
549 
putByte(long address, byte value)550     public abstract void putByte(long address, byte value);
551 
getInt(long address)552     public abstract int getInt(long address);
553 
putInt(long address, int value)554     public abstract void putInt(long address, int value);
555 
getLong(long address)556     public abstract long getLong(long address);
557 
putLong(long address, long value)558     public abstract void putLong(long address, long value);
559 
getStaticObject(Field field)560     public abstract Object getStaticObject(Field field);
561 
copyMemory(long srcOffset, byte[] target, long targetIndex, long length)562     public abstract void copyMemory(long srcOffset, byte[] target, long targetIndex, long length);
563 
copyMemory(byte[] src, long srcIndex, long targetOffset, long length)564     public abstract void copyMemory(byte[] src, long srcIndex, long targetOffset, long length);
565   }
566 
567   private static final class JvmMemoryAccessor extends MemoryAccessor {
568 
JvmMemoryAccessor(sun.misc.Unsafe unsafe)569     JvmMemoryAccessor(sun.misc.Unsafe unsafe) {
570       super(unsafe);
571     }
572 
573     @Override
getByte(long address)574     public byte getByte(long address) {
575       return unsafe.getByte(address);
576     }
577 
578     @Override
putByte(long address, byte value)579     public void putByte(long address, byte value) {
580       unsafe.putByte(address, value);
581     }
582 
583     @Override
getInt(long address)584     public int getInt(long address) {
585       return unsafe.getInt(address);
586     }
587 
588     @Override
putInt(long address, int value)589     public void putInt(long address, int value) {
590       unsafe.putInt(address, value);
591     }
592 
593     @Override
getLong(long address)594     public long getLong(long address) {
595       return unsafe.getLong(address);
596     }
597 
598     @Override
putLong(long address, long value)599     public void putLong(long address, long value) {
600       unsafe.putLong(address, value);
601     }
602 
603     @Override
getByte(Object target, long offset)604     public byte getByte(Object target, long offset) {
605       return unsafe.getByte(target, offset);
606     }
607 
608     @Override
putByte(Object target, long offset, byte value)609     public void putByte(Object target, long offset, byte value) {
610       unsafe.putByte(target, offset, value);
611     }
612 
613     @Override
getBoolean(Object target, long offset)614     public boolean getBoolean(Object target, long offset) {
615       return unsafe.getBoolean(target, offset);
616     }
617 
618     @Override
putBoolean(Object target, long offset, boolean value)619     public void putBoolean(Object target, long offset, boolean value) {
620       unsafe.putBoolean(target, offset, value);
621     }
622 
623     @Override
getFloat(Object target, long offset)624     public float getFloat(Object target, long offset) {
625       return unsafe.getFloat(target, offset);
626     }
627 
628     @Override
putFloat(Object target, long offset, float value)629     public void putFloat(Object target, long offset, float value) {
630       unsafe.putFloat(target, offset, value);
631     }
632 
633     @Override
getDouble(Object target, long offset)634     public double getDouble(Object target, long offset) {
635       return unsafe.getDouble(target, offset);
636     }
637 
638     @Override
putDouble(Object target, long offset, double value)639     public void putDouble(Object target, long offset, double value) {
640       unsafe.putDouble(target, offset, value);
641     }
642 
643     @Override
copyMemory(long srcOffset, byte[] target, long targetIndex, long length)644     public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
645       unsafe.copyMemory(null, srcOffset, target, BYTE_ARRAY_BASE_OFFSET + targetIndex, length);
646     }
647 
648     @Override
copyMemory(byte[] src, long srcIndex, long targetOffset, long length)649     public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
650       unsafe.copyMemory(src, BYTE_ARRAY_BASE_OFFSET + srcIndex, null, targetOffset, length);
651     }
652 
653     @Override
getStaticObject(Field field)654     public Object getStaticObject(Field field) {
655       return getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field));
656     }
657   }
658 
659 }
660