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 Class<?> MEMORY_CLASS = Android.getMemoryClass(); 47 private static final boolean IS_ANDROID_64 = determineAndroidSupportByAddressSize(long.class); 48 private static final boolean IS_ANDROID_32 = determineAndroidSupportByAddressSize(int.class); 49 private static final MemoryAccessor MEMORY_ACCESSOR = getMemoryAccessor(); 50 private static final boolean HAS_UNSAFE_BYTEBUFFER_OPERATIONS = 51 supportsUnsafeByteBufferOperations(); 52 private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = supportsUnsafeArrayOperations(); 53 54 static final long BYTE_ARRAY_BASE_OFFSET = arrayBaseOffset(byte[].class); 55 // Micro-optimization: we can assume a scale of 1 and skip the multiply 56 // private static final long BYTE_ARRAY_INDEX_SCALE = 1; 57 58 private static final long BOOLEAN_ARRAY_BASE_OFFSET = arrayBaseOffset(boolean[].class); 59 private static final long BOOLEAN_ARRAY_INDEX_SCALE = arrayIndexScale(boolean[].class); 60 61 private static final long INT_ARRAY_BASE_OFFSET = arrayBaseOffset(int[].class); 62 private static final long INT_ARRAY_INDEX_SCALE = arrayIndexScale(int[].class); 63 64 private static final long LONG_ARRAY_BASE_OFFSET = arrayBaseOffset(long[].class); 65 private static final long LONG_ARRAY_INDEX_SCALE = arrayIndexScale(long[].class); 66 67 private static final long FLOAT_ARRAY_BASE_OFFSET = arrayBaseOffset(float[].class); 68 private static final long FLOAT_ARRAY_INDEX_SCALE = arrayIndexScale(float[].class); 69 70 private static final long DOUBLE_ARRAY_BASE_OFFSET = arrayBaseOffset(double[].class); 71 private static final long DOUBLE_ARRAY_INDEX_SCALE = arrayIndexScale(double[].class); 72 73 private static final long OBJECT_ARRAY_BASE_OFFSET = arrayBaseOffset(Object[].class); 74 private static final long OBJECT_ARRAY_INDEX_SCALE = arrayIndexScale(Object[].class); 75 76 private static final long BUFFER_ADDRESS_OFFSET = fieldOffset(bufferAddressField()); 77 78 private static final int STRIDE = 8; 79 private static final int STRIDE_ALIGNMENT_MASK = STRIDE - 1; 80 private static final int BYTE_ARRAY_ALIGNMENT = 81 (int) (BYTE_ARRAY_BASE_OFFSET & STRIDE_ALIGNMENT_MASK); 82 83 static final boolean IS_BIG_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; 84 UnsafeUtil()85 private UnsafeUtil() {} 86 hasUnsafeArrayOperations()87 static boolean hasUnsafeArrayOperations() { 88 return HAS_UNSAFE_ARRAY_OPERATIONS; 89 } 90 hasUnsafeByteBufferOperations()91 static boolean hasUnsafeByteBufferOperations() { 92 return HAS_UNSAFE_BYTEBUFFER_OPERATIONS; 93 } 94 isAndroid64()95 static boolean isAndroid64() { 96 return IS_ANDROID_64; 97 } 98 99 @SuppressWarnings("unchecked") // safe by method contract allocateInstance(Class<T> clazz)100 static <T> T allocateInstance(Class<T> clazz) { 101 try { 102 return (T) UNSAFE.allocateInstance(clazz); 103 } catch (InstantiationException e) { 104 throw new IllegalStateException(e); 105 } 106 } 107 objectFieldOffset(Field field)108 static long objectFieldOffset(Field field) { 109 return MEMORY_ACCESSOR.objectFieldOffset(field); 110 } 111 arrayBaseOffset(Class<?> clazz)112 private static int arrayBaseOffset(Class<?> clazz) { 113 return HAS_UNSAFE_ARRAY_OPERATIONS ? MEMORY_ACCESSOR.arrayBaseOffset(clazz) : -1; 114 } 115 arrayIndexScale(Class<?> clazz)116 private static int arrayIndexScale(Class<?> clazz) { 117 return HAS_UNSAFE_ARRAY_OPERATIONS ? MEMORY_ACCESSOR.arrayIndexScale(clazz) : -1; 118 } 119 getByte(Object target, long offset)120 static byte getByte(Object target, long offset) { 121 return MEMORY_ACCESSOR.getByte(target, offset); 122 } 123 putByte(Object target, long offset, byte value)124 static void putByte(Object target, long offset, byte value) { 125 MEMORY_ACCESSOR.putByte(target, offset, value); 126 } 127 getInt(Object target, long offset)128 static int getInt(Object target, long offset) { 129 return MEMORY_ACCESSOR.getInt(target, offset); 130 } 131 putInt(Object target, long offset, int value)132 static void putInt(Object target, long offset, int value) { 133 MEMORY_ACCESSOR.putInt(target, offset, value); 134 } 135 getLong(Object target, long offset)136 static long getLong(Object target, long offset) { 137 return MEMORY_ACCESSOR.getLong(target, offset); 138 } 139 putLong(Object target, long offset, long value)140 static void putLong(Object target, long offset, long value) { 141 MEMORY_ACCESSOR.putLong(target, offset, value); 142 } 143 getBoolean(Object target, long offset)144 static boolean getBoolean(Object target, long offset) { 145 return MEMORY_ACCESSOR.getBoolean(target, offset); 146 } 147 putBoolean(Object target, long offset, boolean value)148 static void putBoolean(Object target, long offset, boolean value) { 149 MEMORY_ACCESSOR.putBoolean(target, offset, value); 150 } 151 getFloat(Object target, long offset)152 static float getFloat(Object target, long offset) { 153 return MEMORY_ACCESSOR.getFloat(target, offset); 154 } 155 putFloat(Object target, long offset, float value)156 static void putFloat(Object target, long offset, float value) { 157 MEMORY_ACCESSOR.putFloat(target, offset, value); 158 } 159 getDouble(Object target, long offset)160 static double getDouble(Object target, long offset) { 161 return MEMORY_ACCESSOR.getDouble(target, offset); 162 } 163 putDouble(Object target, long offset, double value)164 static void putDouble(Object target, long offset, double value) { 165 MEMORY_ACCESSOR.putDouble(target, offset, value); 166 } 167 getObject(Object target, long offset)168 static Object getObject(Object target, long offset) { 169 return MEMORY_ACCESSOR.getObject(target, offset); 170 } 171 putObject(Object target, long offset, Object value)172 static void putObject(Object target, long offset, Object value) { 173 MEMORY_ACCESSOR.putObject(target, offset, value); 174 } 175 getByte(byte[] target, long index)176 static byte getByte(byte[] target, long index) { 177 return MEMORY_ACCESSOR.getByte(target, BYTE_ARRAY_BASE_OFFSET + index); 178 } 179 putByte(byte[] target, long index, byte value)180 static void putByte(byte[] target, long index, byte value) { 181 MEMORY_ACCESSOR.putByte(target, BYTE_ARRAY_BASE_OFFSET + index, value); 182 } 183 getInt(int[] target, long index)184 static int getInt(int[] target, long index) { 185 return MEMORY_ACCESSOR.getInt(target, INT_ARRAY_BASE_OFFSET + (index * INT_ARRAY_INDEX_SCALE)); 186 } 187 putInt(int[] target, long index, int value)188 static void putInt(int[] target, long index, int value) { 189 MEMORY_ACCESSOR.putInt(target, INT_ARRAY_BASE_OFFSET + (index * INT_ARRAY_INDEX_SCALE), value); 190 } 191 getLong(long[] target, long index)192 static long getLong(long[] target, long index) { 193 return MEMORY_ACCESSOR.getLong( 194 target, LONG_ARRAY_BASE_OFFSET + (index * LONG_ARRAY_INDEX_SCALE)); 195 } 196 putLong(long[] target, long index, long value)197 static void putLong(long[] target, long index, long value) { 198 MEMORY_ACCESSOR.putLong( 199 target, LONG_ARRAY_BASE_OFFSET + (index * LONG_ARRAY_INDEX_SCALE), value); 200 } 201 getBoolean(boolean[] target, long index)202 static boolean getBoolean(boolean[] target, long index) { 203 return MEMORY_ACCESSOR.getBoolean( 204 target, BOOLEAN_ARRAY_BASE_OFFSET + (index * BOOLEAN_ARRAY_INDEX_SCALE)); 205 } 206 putBoolean(boolean[] target, long index, boolean value)207 static void putBoolean(boolean[] target, long index, boolean value) { 208 MEMORY_ACCESSOR.putBoolean( 209 target, BOOLEAN_ARRAY_BASE_OFFSET + (index * BOOLEAN_ARRAY_INDEX_SCALE), value); 210 } 211 getFloat(float[] target, long index)212 static float getFloat(float[] target, long index) { 213 return MEMORY_ACCESSOR.getFloat( 214 target, FLOAT_ARRAY_BASE_OFFSET + (index * FLOAT_ARRAY_INDEX_SCALE)); 215 } 216 putFloat(float[] target, long index, float value)217 static void putFloat(float[] target, long index, float value) { 218 MEMORY_ACCESSOR.putFloat( 219 target, FLOAT_ARRAY_BASE_OFFSET + (index * FLOAT_ARRAY_INDEX_SCALE), value); 220 } 221 getDouble(double[] target, long index)222 static double getDouble(double[] target, long index) { 223 return MEMORY_ACCESSOR.getDouble( 224 target, DOUBLE_ARRAY_BASE_OFFSET + (index * DOUBLE_ARRAY_INDEX_SCALE)); 225 } 226 putDouble(double[] target, long index, double value)227 static void putDouble(double[] target, long index, double value) { 228 MEMORY_ACCESSOR.putDouble( 229 target, DOUBLE_ARRAY_BASE_OFFSET + (index * DOUBLE_ARRAY_INDEX_SCALE), value); 230 } 231 getObject(Object[] target, long index)232 static Object getObject(Object[] target, long index) { 233 return MEMORY_ACCESSOR.getObject( 234 target, OBJECT_ARRAY_BASE_OFFSET + (index * OBJECT_ARRAY_INDEX_SCALE)); 235 } 236 putObject(Object[] target, long index, Object value)237 static void putObject(Object[] target, long index, Object value) { 238 MEMORY_ACCESSOR.putObject( 239 target, OBJECT_ARRAY_BASE_OFFSET + (index * OBJECT_ARRAY_INDEX_SCALE), value); 240 } 241 copyMemory(byte[] src, long srcIndex, long targetOffset, long length)242 static void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) { 243 MEMORY_ACCESSOR.copyMemory(src, srcIndex, targetOffset, length); 244 } 245 copyMemory(long srcOffset, byte[] target, long targetIndex, long length)246 static void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) { 247 MEMORY_ACCESSOR.copyMemory(srcOffset, target, targetIndex, length); 248 } 249 copyMemory(byte[] src, long srcIndex, byte[] target, long targetIndex, long length)250 static void copyMemory(byte[] src, long srcIndex, byte[] target, long targetIndex, long length) { 251 System.arraycopy(src, (int) srcIndex, target, (int) targetIndex, (int) length); 252 } 253 getByte(long address)254 static byte getByte(long address) { 255 return MEMORY_ACCESSOR.getByte(address); 256 } 257 putByte(long address, byte value)258 static void putByte(long address, byte value) { 259 MEMORY_ACCESSOR.putByte(address, value); 260 } 261 getInt(long address)262 static int getInt(long address) { 263 return MEMORY_ACCESSOR.getInt(address); 264 } 265 putInt(long address, int value)266 static void putInt(long address, int value) { 267 MEMORY_ACCESSOR.putInt(address, value); 268 } 269 getLong(long address)270 static long getLong(long address) { 271 return MEMORY_ACCESSOR.getLong(address); 272 } 273 putLong(long address, long value)274 static void putLong(long address, long value) { 275 MEMORY_ACCESSOR.putLong(address, value); 276 } 277 278 /** Gets the offset of the {@code address} field of the given direct {@link ByteBuffer}. */ addressOffset(ByteBuffer buffer)279 static long addressOffset(ByteBuffer buffer) { 280 return MEMORY_ACCESSOR.getLong(buffer, BUFFER_ADDRESS_OFFSET); 281 } 282 getStaticObject(Field field)283 static Object getStaticObject(Field field) { 284 return MEMORY_ACCESSOR.getStaticObject(field); 285 } 286 287 /** 288 * Gets the {@code sun.misc.Unsafe} instance, or {@code null} if not available on this platform. 289 */ getUnsafe()290 static sun.misc.Unsafe getUnsafe() { 291 sun.misc.Unsafe unsafe = null; 292 try { 293 unsafe = 294 AccessController.doPrivileged( 295 new PrivilegedExceptionAction<sun.misc.Unsafe>() { 296 @Override 297 public sun.misc.Unsafe run() throws Exception { 298 Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class; 299 300 for (Field f : k.getDeclaredFields()) { 301 f.setAccessible(true); 302 Object x = f.get(null); 303 if (k.isInstance(x)) { 304 return k.cast(x); 305 } 306 } 307 // The sun.misc.Unsafe field does not exist. 308 return null; 309 } 310 }); 311 } catch (Throwable e) { 312 // Catching Throwable here due to the fact that Google AppEngine raises NoClassDefFoundError 313 // for Unsafe. 314 } 315 return unsafe; 316 } 317 318 /** Get a {@link MemoryAccessor} appropriate for the platform, or null if not supported. */ getMemoryAccessor()319 private static MemoryAccessor getMemoryAccessor() { 320 if (UNSAFE == null) { 321 return null; 322 } 323 if (Android.isOnAndroidDevice()) { 324 if (IS_ANDROID_64) { 325 return new Android64MemoryAccessor(UNSAFE); 326 } else if (IS_ANDROID_32) { 327 return new Android32MemoryAccessor(UNSAFE); 328 } else { 329 return null; 330 } 331 } 332 333 return new JvmMemoryAccessor(UNSAFE); 334 } 335 336 /** Indicates whether or not unsafe array operations are supported on this platform. */ supportsUnsafeArrayOperations()337 private static boolean supportsUnsafeArrayOperations() { 338 if (UNSAFE == null) { 339 return false; 340 } 341 try { 342 Class<?> clazz = UNSAFE.getClass(); 343 clazz.getMethod("objectFieldOffset", Field.class); 344 clazz.getMethod("arrayBaseOffset", Class.class); 345 clazz.getMethod("arrayIndexScale", Class.class); 346 clazz.getMethod("getInt", Object.class, long.class); 347 clazz.getMethod("putInt", Object.class, long.class, int.class); 348 clazz.getMethod("getLong", Object.class, long.class); 349 clazz.getMethod("putLong", Object.class, long.class, long.class); 350 clazz.getMethod("getObject", Object.class, long.class); 351 clazz.getMethod("putObject", Object.class, long.class, Object.class); 352 if (Android.isOnAndroidDevice()) { 353 return true; 354 } 355 clazz.getMethod("getByte", Object.class, long.class); 356 clazz.getMethod("putByte", Object.class, long.class, byte.class); 357 clazz.getMethod("getBoolean", Object.class, long.class); 358 clazz.getMethod("putBoolean", Object.class, long.class, boolean.class); 359 clazz.getMethod("getFloat", Object.class, long.class); 360 clazz.getMethod("putFloat", Object.class, long.class, float.class); 361 clazz.getMethod("getDouble", Object.class, long.class); 362 clazz.getMethod("putDouble", Object.class, long.class, double.class); 363 364 return true; 365 } catch (Throwable e) { 366 logger.log( 367 Level.WARNING, 368 "platform method missing - proto runtime falling back to safer methods: " + e); 369 } 370 return false; 371 } 372 supportsUnsafeByteBufferOperations()373 private static boolean supportsUnsafeByteBufferOperations() { 374 if (UNSAFE == null) { 375 return false; 376 } 377 try { 378 Class<?> clazz = UNSAFE.getClass(); 379 // Methods for getting direct buffer address. 380 clazz.getMethod("objectFieldOffset", Field.class); 381 clazz.getMethod("getLong", Object.class, long.class); 382 383 if (bufferAddressField() == null) { 384 return false; 385 } 386 387 if (Android.isOnAndroidDevice()) { 388 return true; 389 } 390 clazz.getMethod("getByte", long.class); 391 clazz.getMethod("putByte", long.class, byte.class); 392 clazz.getMethod("getInt", long.class); 393 clazz.getMethod("putInt", long.class, int.class); 394 clazz.getMethod("getLong", long.class); 395 clazz.getMethod("putLong", long.class, long.class); 396 clazz.getMethod("copyMemory", long.class, long.class, long.class); 397 clazz.getMethod("copyMemory", Object.class, long.class, Object.class, long.class, long.class); 398 return true; 399 } catch (Throwable e) { 400 logger.log( 401 Level.WARNING, 402 "platform method missing - proto runtime falling back to safer methods: " + e); 403 } 404 return false; 405 } 406 determineAndroidSupportByAddressSize(Class<?> addressClass)407 private static boolean determineAndroidSupportByAddressSize(Class<?> addressClass) { 408 if (!Android.isOnAndroidDevice()) { 409 return false; 410 } 411 try { 412 Class<?> clazz = MEMORY_CLASS; 413 clazz.getMethod("peekLong", addressClass, boolean.class); 414 clazz.getMethod("pokeLong", addressClass, long.class, boolean.class); 415 clazz.getMethod("pokeInt", addressClass, int.class, boolean.class); 416 clazz.getMethod("peekInt", addressClass, boolean.class); 417 clazz.getMethod("pokeByte", addressClass, byte.class); 418 clazz.getMethod("peekByte", addressClass); 419 clazz.getMethod("pokeByteArray", addressClass, byte[].class, int.class, int.class); 420 clazz.getMethod("peekByteArray", addressClass, byte[].class, int.class, int.class); 421 return true; 422 } catch (Throwable t) { 423 return false; 424 } 425 } 426 427 /** Finds the address field within a direct {@link Buffer}. */ bufferAddressField()428 private static Field bufferAddressField() { 429 if (Android.isOnAndroidDevice()) { 430 // Old versions of Android had renamed the address field to 'effectiveDirectAddress', but 431 // recent versions of Android (>M?) use the OpenJDK implementation. Fall through in that case. 432 Field field = field(Buffer.class, "effectiveDirectAddress"); 433 if (field != null) { 434 return field; 435 } 436 } 437 Field field = field(Buffer.class, "address"); 438 return field != null && field.getType() == long.class ? field : null; 439 } 440 441 /** 442 * Returns the index of the first byte where left and right differ, in the range [0, 8]. If {@code 443 * left == right}, the result will be 8, otherwise less than 8. 444 * 445 * <p>This counts from the *first* byte, which may be the most or least significant byte depending 446 * on the system endianness. 447 */ firstDifferingByteIndexNativeEndian(long left, long right)448 private static int firstDifferingByteIndexNativeEndian(long left, long right) { 449 int n = 450 IS_BIG_ENDIAN 451 ? Long.numberOfLeadingZeros(left ^ right) 452 : Long.numberOfTrailingZeros(left ^ right); 453 return n >> 3; 454 } 455 456 /** 457 * Returns the lowest {@code index} such that {@code 0 <= index < length} and {@code left[leftOff 458 * + index] != right[rightOff + index]}. If no such value exists -- if {@code left} and {@code 459 * right} match up to {@code length} bytes from their respective offsets -- returns -1. 460 * 461 * <p>{@code leftOff + length} must be less than or equal to {@code left.length}, and the same for 462 * {@code right}. 463 */ mismatch(byte[] left, int leftOff, byte[] right, int rightOff, int length)464 static int mismatch(byte[] left, int leftOff, byte[] right, int rightOff, int length) { 465 if (leftOff < 0 466 || rightOff < 0 467 || length < 0 468 || leftOff + length > left.length 469 || rightOff + length > right.length) { 470 throw new IndexOutOfBoundsException(); 471 } 472 473 int index = 0; 474 if (HAS_UNSAFE_ARRAY_OPERATIONS) { 475 int leftAlignment = (BYTE_ARRAY_ALIGNMENT + leftOff) & STRIDE_ALIGNMENT_MASK; 476 477 // Most CPUs handle getting chunks of bytes better on addresses that are a multiple of 4 478 // or 8. 479 // We walk one byte at a time until the left address, at least, is a multiple of 8. 480 // If the right address is, too, so much the better. 481 for (; 482 index < length && (leftAlignment & STRIDE_ALIGNMENT_MASK) != 0; 483 index++, leftAlignment++) { 484 if (left[leftOff + index] != right[rightOff + index]) { 485 return index; 486 } 487 } 488 489 // Stride! Grab eight bytes at a time from left and right and check them for equality. 490 491 int strideLength = ((length - index) & ~STRIDE_ALIGNMENT_MASK) + index; 492 // strideLength is the point where we want to stop striding: it differs from index by 493 // a multiple of STRIDE, and it's the largest such number <= length. 494 495 for (; index < strideLength; index += STRIDE) { 496 long leftLongWord = getLong(left, BYTE_ARRAY_BASE_OFFSET + leftOff + index); 497 long rightLongWord = getLong(right, BYTE_ARRAY_BASE_OFFSET + rightOff + index); 498 if (leftLongWord != rightLongWord) { 499 // one of these eight bytes differ! use a helper to find out which one 500 return index + firstDifferingByteIndexNativeEndian(leftLongWord, rightLongWord); 501 } 502 } 503 } 504 505 // If we were able to stride, there are at most STRIDE - 1 bytes left to compare. 506 // If we weren't, then this loop covers the whole thing. 507 for (; index < length; index++) { 508 if (left[leftOff + index] != right[rightOff + index]) { 509 return index; 510 } 511 } 512 return -1; 513 } 514 515 /** 516 * Returns the offset of the provided field, or {@code -1} if {@code sun.misc.Unsafe} is not 517 * available. 518 */ fieldOffset(Field field)519 private static long fieldOffset(Field field) { 520 return field == null || MEMORY_ACCESSOR == null ? -1 : MEMORY_ACCESSOR.objectFieldOffset(field); 521 } 522 523 /** 524 * Gets the field with the given name within the class, or {@code null} if not found. 525 */ field(Class<?> clazz, String fieldName)526 private static Field field(Class<?> clazz, String fieldName) { 527 Field field; 528 try { 529 field = clazz.getDeclaredField(fieldName); 530 } catch (Throwable t) { 531 // Failed to access the fields. 532 field = null; 533 } 534 return field; 535 } 536 537 private abstract static class MemoryAccessor { 538 539 sun.misc.Unsafe unsafe; 540 MemoryAccessor(sun.misc.Unsafe unsafe)541 MemoryAccessor(sun.misc.Unsafe unsafe) { 542 this.unsafe = unsafe; 543 } 544 objectFieldOffset(Field field)545 public final long objectFieldOffset(Field field) { 546 return unsafe.objectFieldOffset(field); 547 } 548 getByte(Object target, long offset)549 public abstract byte getByte(Object target, long offset); 550 putByte(Object target, long offset, byte value)551 public abstract void putByte(Object target, long offset, byte value); 552 getInt(Object target, long offset)553 public final int getInt(Object target, long offset) { 554 return unsafe.getInt(target, offset); 555 } 556 putInt(Object target, long offset, int value)557 public final void putInt(Object target, long offset, int value) { 558 unsafe.putInt(target, offset, value); 559 } 560 getLong(Object target, long offset)561 public final long getLong(Object target, long offset) { 562 return unsafe.getLong(target, offset); 563 } 564 putLong(Object target, long offset, long value)565 public final void putLong(Object target, long offset, long value) { 566 unsafe.putLong(target, offset, value); 567 } 568 getBoolean(Object target, long offset)569 public abstract boolean getBoolean(Object target, long offset); 570 putBoolean(Object target, long offset, boolean value)571 public abstract void putBoolean(Object target, long offset, boolean value); 572 getFloat(Object target, long offset)573 public abstract float getFloat(Object target, long offset); 574 putFloat(Object target, long offset, float value)575 public abstract void putFloat(Object target, long offset, float value); 576 getDouble(Object target, long offset)577 public abstract double getDouble(Object target, long offset); 578 putDouble(Object target, long offset, double value)579 public abstract void putDouble(Object target, long offset, double value); 580 getObject(Object target, long offset)581 public final Object getObject(Object target, long offset) { 582 return unsafe.getObject(target, offset); 583 } 584 putObject(Object target, long offset, Object value)585 public final void putObject(Object target, long offset, Object value) { 586 unsafe.putObject(target, offset, value); 587 } 588 arrayBaseOffset(Class<?> clazz)589 public final int arrayBaseOffset(Class<?> clazz) { 590 return unsafe.arrayBaseOffset(clazz); 591 } 592 arrayIndexScale(Class<?> clazz)593 public final int arrayIndexScale(Class<?> clazz) { 594 return unsafe.arrayIndexScale(clazz); 595 } 596 getByte(long address)597 public abstract byte getByte(long address); 598 putByte(long address, byte value)599 public abstract void putByte(long address, byte value); 600 getInt(long address)601 public abstract int getInt(long address); 602 putInt(long address, int value)603 public abstract void putInt(long address, int value); 604 getLong(long address)605 public abstract long getLong(long address); 606 putLong(long address, long value)607 public abstract void putLong(long address, long value); 608 getStaticObject(Field field)609 public abstract Object getStaticObject(Field field); 610 copyMemory(long srcOffset, byte[] target, long targetIndex, long length)611 public abstract void copyMemory(long srcOffset, byte[] target, long targetIndex, long length); 612 copyMemory(byte[] src, long srcIndex, long targetOffset, long length)613 public abstract void copyMemory(byte[] src, long srcIndex, long targetOffset, long length); 614 } 615 616 private static final class JvmMemoryAccessor extends MemoryAccessor { 617 JvmMemoryAccessor(sun.misc.Unsafe unsafe)618 JvmMemoryAccessor(sun.misc.Unsafe unsafe) { 619 super(unsafe); 620 } 621 622 @Override getByte(long address)623 public byte getByte(long address) { 624 return unsafe.getByte(address); 625 } 626 627 @Override putByte(long address, byte value)628 public void putByte(long address, byte value) { 629 unsafe.putByte(address, value); 630 } 631 632 @Override getInt(long address)633 public int getInt(long address) { 634 return unsafe.getInt(address); 635 } 636 637 @Override putInt(long address, int value)638 public void putInt(long address, int value) { 639 unsafe.putInt(address, value); 640 } 641 642 @Override getLong(long address)643 public long getLong(long address) { 644 return unsafe.getLong(address); 645 } 646 647 @Override putLong(long address, long value)648 public void putLong(long address, long value) { 649 unsafe.putLong(address, value); 650 } 651 652 @Override getByte(Object target, long offset)653 public byte getByte(Object target, long offset) { 654 return unsafe.getByte(target, offset); 655 } 656 657 @Override putByte(Object target, long offset, byte value)658 public void putByte(Object target, long offset, byte value) { 659 unsafe.putByte(target, offset, value); 660 } 661 662 @Override getBoolean(Object target, long offset)663 public boolean getBoolean(Object target, long offset) { 664 return unsafe.getBoolean(target, offset); 665 } 666 667 @Override putBoolean(Object target, long offset, boolean value)668 public void putBoolean(Object target, long offset, boolean value) { 669 unsafe.putBoolean(target, offset, value); 670 } 671 672 @Override getFloat(Object target, long offset)673 public float getFloat(Object target, long offset) { 674 return unsafe.getFloat(target, offset); 675 } 676 677 @Override putFloat(Object target, long offset, float value)678 public void putFloat(Object target, long offset, float value) { 679 unsafe.putFloat(target, offset, value); 680 } 681 682 @Override getDouble(Object target, long offset)683 public double getDouble(Object target, long offset) { 684 return unsafe.getDouble(target, offset); 685 } 686 687 @Override putDouble(Object target, long offset, double value)688 public void putDouble(Object target, long offset, double value) { 689 unsafe.putDouble(target, offset, value); 690 } 691 692 @Override copyMemory(long srcOffset, byte[] target, long targetIndex, long length)693 public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) { 694 unsafe.copyMemory(null, srcOffset, target, BYTE_ARRAY_BASE_OFFSET + targetIndex, length); 695 } 696 697 @Override copyMemory(byte[] src, long srcIndex, long targetOffset, long length)698 public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) { 699 unsafe.copyMemory(src, BYTE_ARRAY_BASE_OFFSET + srcIndex, null, targetOffset, length); 700 } 701 702 @Override getStaticObject(Field field)703 public Object getStaticObject(Field field) { 704 return getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field)); 705 } 706 } 707 708 private static final class Android64MemoryAccessor extends MemoryAccessor { 709 Android64MemoryAccessor(sun.misc.Unsafe unsafe)710 Android64MemoryAccessor(sun.misc.Unsafe unsafe) { 711 super(unsafe); 712 } 713 714 @Override getByte(long address)715 public byte getByte(long address) { 716 throw new UnsupportedOperationException(); 717 } 718 719 @Override putByte(long address, byte value)720 public void putByte(long address, byte value) { 721 throw new UnsupportedOperationException(); 722 } 723 724 @Override getInt(long address)725 public int getInt(long address) { 726 throw new UnsupportedOperationException(); 727 } 728 729 @Override putInt(long address, int value)730 public void putInt(long address, int value) { 731 throw new UnsupportedOperationException(); 732 } 733 734 @Override getLong(long address)735 public long getLong(long address) { 736 throw new UnsupportedOperationException(); 737 } 738 739 @Override putLong(long address, long value)740 public void putLong(long address, long value) { 741 throw new UnsupportedOperationException(); 742 } 743 744 @Override getByte(Object target, long offset)745 public byte getByte(Object target, long offset) { 746 if (IS_BIG_ENDIAN) { 747 return getByteBigEndian(target, offset); 748 } else { 749 return getByteLittleEndian(target, offset); 750 } 751 } 752 753 @Override putByte(Object target, long offset, byte value)754 public void putByte(Object target, long offset, byte value) { 755 if (IS_BIG_ENDIAN) { 756 putByteBigEndian(target, offset, value); 757 } else { 758 putByteLittleEndian(target, offset, value); 759 } 760 } 761 762 @Override getBoolean(Object target, long offset)763 public boolean getBoolean(Object target, long offset) { 764 if (IS_BIG_ENDIAN) { 765 return getBooleanBigEndian(target, offset); 766 } else { 767 return getBooleanLittleEndian(target, offset); 768 } 769 } 770 771 @Override putBoolean(Object target, long offset, boolean value)772 public void putBoolean(Object target, long offset, boolean value) { 773 if (IS_BIG_ENDIAN) { 774 putBooleanBigEndian(target, offset, value); 775 } else { 776 putBooleanLittleEndian(target, offset, value); 777 } 778 } 779 780 @Override getFloat(Object target, long offset)781 public float getFloat(Object target, long offset) { 782 return Float.intBitsToFloat(getInt(target, offset)); 783 } 784 785 @Override putFloat(Object target, long offset, float value)786 public void putFloat(Object target, long offset, float value) { 787 putInt(target, offset, Float.floatToIntBits(value)); 788 } 789 790 @Override getDouble(Object target, long offset)791 public double getDouble(Object target, long offset) { 792 return Double.longBitsToDouble(getLong(target, offset)); 793 } 794 795 @Override putDouble(Object target, long offset, double value)796 public void putDouble(Object target, long offset, double value) { 797 putLong(target, offset, Double.doubleToLongBits(value)); 798 } 799 800 @Override copyMemory(long srcOffset, byte[] target, long targetIndex, long length)801 public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) { 802 throw new UnsupportedOperationException(); 803 } 804 805 @Override copyMemory(byte[] src, long srcIndex, long targetOffset, long length)806 public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) { 807 throw new UnsupportedOperationException(); 808 } 809 810 @Override getStaticObject(Field field)811 public Object getStaticObject(Field field) { 812 try { 813 return field.get(null); 814 } catch (IllegalAccessException e) { 815 return null; 816 } 817 } 818 } 819 820 private static final class Android32MemoryAccessor extends MemoryAccessor { 821 822 /** Mask used to convert a 64 bit memory address to a 32 bit address. */ 823 private static final long SMALL_ADDRESS_MASK = 0x00000000FFFFFFFF; 824 825 /** Truncate a {@code long} address into a short {@code int} address. */ smallAddress(long address)826 private static int smallAddress(long address) { 827 return (int) (SMALL_ADDRESS_MASK & address); 828 } 829 Android32MemoryAccessor(sun.misc.Unsafe unsafe)830 Android32MemoryAccessor(sun.misc.Unsafe unsafe) { 831 super(unsafe); 832 } 833 834 @Override getByte(long address)835 public byte getByte(long address) { 836 throw new UnsupportedOperationException(); 837 } 838 839 @Override putByte(long address, byte value)840 public void putByte(long address, byte value) { 841 throw new UnsupportedOperationException(); 842 } 843 844 @Override getInt(long address)845 public int getInt(long address) { 846 throw new UnsupportedOperationException(); 847 } 848 849 @Override putInt(long address, int value)850 public void putInt(long address, int value) { 851 throw new UnsupportedOperationException(); 852 } 853 854 @Override getLong(long address)855 public long getLong(long address) { 856 throw new UnsupportedOperationException(); 857 } 858 859 @Override putLong(long address, long value)860 public void putLong(long address, long value) { 861 throw new UnsupportedOperationException(); 862 } 863 864 @Override getByte(Object target, long offset)865 public byte getByte(Object target, long offset) { 866 if (IS_BIG_ENDIAN) { 867 return getByteBigEndian(target, offset); 868 } else { 869 return getByteLittleEndian(target, offset); 870 } 871 } 872 873 @Override putByte(Object target, long offset, byte value)874 public void putByte(Object target, long offset, byte value) { 875 if (IS_BIG_ENDIAN) { 876 putByteBigEndian(target, offset, value); 877 } else { 878 putByteLittleEndian(target, offset, value); 879 } 880 } 881 882 @Override getBoolean(Object target, long offset)883 public boolean getBoolean(Object target, long offset) { 884 if (IS_BIG_ENDIAN) { 885 return getBooleanBigEndian(target, offset); 886 } else { 887 return getBooleanLittleEndian(target, offset); 888 } 889 } 890 891 @Override putBoolean(Object target, long offset, boolean value)892 public void putBoolean(Object target, long offset, boolean value) { 893 if (IS_BIG_ENDIAN) { 894 putBooleanBigEndian(target, offset, value); 895 } else { 896 putBooleanLittleEndian(target, offset, value); 897 } 898 } 899 900 @Override getFloat(Object target, long offset)901 public float getFloat(Object target, long offset) { 902 return Float.intBitsToFloat(getInt(target, offset)); 903 } 904 905 @Override putFloat(Object target, long offset, float value)906 public void putFloat(Object target, long offset, float value) { 907 putInt(target, offset, Float.floatToIntBits(value)); 908 } 909 910 @Override getDouble(Object target, long offset)911 public double getDouble(Object target, long offset) { 912 return Double.longBitsToDouble(getLong(target, offset)); 913 } 914 915 @Override putDouble(Object target, long offset, double value)916 public void putDouble(Object target, long offset, double value) { 917 putLong(target, offset, Double.doubleToLongBits(value)); 918 } 919 920 @Override copyMemory(long srcOffset, byte[] target, long targetIndex, long length)921 public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) { 922 throw new UnsupportedOperationException(); 923 } 924 925 @Override copyMemory(byte[] src, long srcIndex, long targetOffset, long length)926 public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) { 927 throw new UnsupportedOperationException(); 928 } 929 930 @Override getStaticObject(Field field)931 public Object getStaticObject(Field field) { 932 try { 933 return field.get(null); 934 } catch (IllegalAccessException e) { 935 return null; 936 } 937 } 938 } 939 getByteBigEndian(Object target, long offset)940 private static byte getByteBigEndian(Object target, long offset) { 941 return (byte) ((getInt(target, offset & ~3) >>> ((~offset & 3) << 3)) & 0xFF); 942 } 943 getByteLittleEndian(Object target, long offset)944 private static byte getByteLittleEndian(Object target, long offset) { 945 return (byte) ((getInt(target, offset & ~3) >>> ((offset & 3) << 3)) & 0xFF); 946 } 947 putByteBigEndian(Object target, long offset, byte value)948 private static void putByteBigEndian(Object target, long offset, byte value) { 949 int intValue = getInt(target, offset & ~3); 950 int shift = ((~(int) offset) & 3) << 3; 951 int output = (intValue & ~(0xFF << shift)) | ((0xFF & value) << shift); 952 putInt(target, offset & ~3, output); 953 } 954 putByteLittleEndian(Object target, long offset, byte value)955 private static void putByteLittleEndian(Object target, long offset, byte value) { 956 int intValue = getInt(target, offset & ~3); 957 int shift = (((int) offset) & 3) << 3; 958 int output = (intValue & ~(0xFF << shift)) | ((0xFF & value) << shift); 959 putInt(target, offset & ~3, output); 960 } 961 getBooleanBigEndian(Object target, long offset)962 private static boolean getBooleanBigEndian(Object target, long offset) { 963 return getByteBigEndian(target, offset) != 0; 964 } 965 getBooleanLittleEndian(Object target, long offset)966 private static boolean getBooleanLittleEndian(Object target, long offset) { 967 return getByteLittleEndian(target, offset) != 0; 968 } 969 putBooleanBigEndian(Object target, long offset, boolean value)970 private static void putBooleanBigEndian(Object target, long offset, boolean value) { 971 putByteBigEndian(target, offset, (byte) (value ? 1 : 0)); 972 } 973 putBooleanLittleEndian(Object target, long offset, boolean value)974 private static void putBooleanLittleEndian(Object target, long offset, boolean value) { 975 putByteLittleEndian(target, offset, (byte) (value ? 1 : 0)); 976 } 977 } 978