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