1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 import java.lang.invoke.MethodHandle; 17 import java.lang.invoke.MethodHandles; 18 import java.lang.invoke.WrongMethodTypeException; 19 import java.lang.reflect.Field; 20 21 public class Main { 22 23 private static final boolean DALVIK_RUN = "Dalvik".equals(System.getProperty("java.vm.name")); 24 25 public static class ValueHolder { 26 public boolean m_z = false; 27 public byte m_b = 0; 28 public char m_c = 'a'; 29 public short m_s = 0; 30 public int m_i = 0; 31 public float m_f = 0.0f; 32 public double m_d = 0.0; 33 public long m_j = 0; 34 public String m_l = "a"; 35 36 public static boolean s_z; 37 public static byte s_b; 38 public static char s_c; 39 public static short s_s; 40 public static int s_i; 41 public static float s_f; 42 public static double s_d; 43 public static long s_j; 44 public static String s_l; 45 46 public final int m_fi = 0xa5a5a5a5; 47 public static final int s_fi = 0x5a5a5a5a; 48 49 private boolean m_pz; 50 private static final boolean s_fz = false; 51 } 52 53 public static class Tester { assertEquals(boolean expected, boolean actual)54 public static void assertEquals(boolean expected, boolean actual) { 55 if (actual != expected) { 56 throw new AssertionError("Actual != Expected (" + actual + " != " + expected + ")"); 57 } 58 } 59 assertEquals(char expected, char actual)60 public static void assertEquals(char expected, char actual) { 61 if (actual != expected) { 62 throw new AssertionError("Actual != Expected (" + actual + " != " + expected + ")"); 63 } 64 } 65 assertEquals(int expected, int actual)66 public static void assertEquals(int expected, int actual) { 67 if (actual != expected) { 68 throw new AssertionError("Actual != Expected (" + actual + " != " + expected + ")"); 69 } 70 } 71 assertTrue(boolean value)72 public static void assertTrue(boolean value) throws AssertionError { 73 if (!value) { 74 throw new AssertionError("Value is not true"); 75 } 76 } 77 fail()78 public static void fail() throws Throwable{ 79 throw new Error("fail"); 80 } 81 } 82 83 public static class InvokeExactTester extends Tester { 84 private enum PrimitiveType { 85 Boolean, 86 Byte, 87 Char, 88 Short, 89 Int, 90 Long, 91 Float, 92 Double, 93 String, 94 } 95 96 private enum AccessorType { 97 IPUT, 98 SPUT, 99 IGET, 100 SGET, 101 } 102 setByte(MethodHandle m, ValueHolder v, byte value, boolean expectFailure)103 static void setByte(MethodHandle m, ValueHolder v, byte value, boolean expectFailure) 104 throws Throwable { 105 boolean exceptionThrown = false; 106 try { 107 if (v == null) { 108 m.invokeExact(value); 109 } 110 else { 111 m.invokeExact(v, value); 112 } 113 } 114 catch (WrongMethodTypeException e) { 115 exceptionThrown = true; 116 } 117 assertEquals(expectFailure, exceptionThrown); 118 } 119 setByte(MethodHandle m, byte value, boolean expectFailure)120 static void setByte(MethodHandle m, byte value, boolean expectFailure) throws Throwable { 121 setByte(m, null, value, expectFailure); 122 } 123 getByte(MethodHandle m, ValueHolder v, byte value, boolean expectFailure)124 static void getByte(MethodHandle m, ValueHolder v, byte value, boolean expectFailure) 125 throws Throwable { 126 boolean exceptionThrown = false; 127 try { 128 final byte got; 129 if (v == null) { 130 got = (byte) m.invokeExact(); 131 } else { 132 got = (byte) m.invokeExact(v); 133 } 134 assertTrue(got == value); 135 } 136 catch (WrongMethodTypeException e) { 137 exceptionThrown = true; 138 } 139 assertEquals(expectFailure, exceptionThrown); 140 } 141 getByte(MethodHandle m, byte value, boolean expectFailure)142 static void getByte(MethodHandle m, byte value, boolean expectFailure) throws Throwable { 143 getByte(m, null, value, expectFailure); 144 } 145 setChar(MethodHandle m, ValueHolder v, char value, boolean expectFailure)146 static void setChar(MethodHandle m, ValueHolder v, char value, boolean expectFailure) 147 throws Throwable { 148 boolean exceptionThrown = false; 149 try { 150 if (v == null) { 151 m.invokeExact(value); 152 } 153 else { 154 m.invokeExact(v, value); 155 } 156 } 157 catch (WrongMethodTypeException e) { 158 exceptionThrown = true; 159 } 160 assertEquals(expectFailure, exceptionThrown); 161 } 162 setChar(MethodHandle m, char value, boolean expectFailure)163 static void setChar(MethodHandle m, char value, boolean expectFailure) throws Throwable { 164 setChar(m, null, value, expectFailure); 165 } 166 getChar(MethodHandle m, ValueHolder v, char value, boolean expectFailure)167 static void getChar(MethodHandle m, ValueHolder v, char value, boolean expectFailure) 168 throws Throwable { 169 boolean exceptionThrown = false; 170 try { 171 final char got; 172 if (v == null) { 173 got = (char) m.invokeExact(); 174 } else { 175 got = (char) m.invokeExact(v); 176 } 177 assertTrue(got == value); 178 } 179 catch (WrongMethodTypeException e) { 180 exceptionThrown = true; 181 } 182 assertEquals(expectFailure, exceptionThrown); 183 } 184 getChar(MethodHandle m, char value, boolean expectFailure)185 static void getChar(MethodHandle m, char value, boolean expectFailure) throws Throwable { 186 getChar(m, null, value, expectFailure); 187 } 188 setShort(MethodHandle m, ValueHolder v, short value, boolean expectFailure)189 static void setShort(MethodHandle m, ValueHolder v, short value, boolean expectFailure) 190 throws Throwable { 191 boolean exceptionThrown = false; 192 try { 193 if (v == null) { 194 m.invokeExact(value); 195 } 196 else { 197 m.invokeExact(v, value); 198 } 199 } 200 catch (WrongMethodTypeException e) { 201 exceptionThrown = true; 202 } 203 assertEquals(expectFailure, exceptionThrown); 204 } 205 setShort(MethodHandle m, short value, boolean expectFailure)206 static void setShort(MethodHandle m, short value, boolean expectFailure) throws Throwable { 207 setShort(m, null, value, expectFailure); 208 } 209 getShort(MethodHandle m, ValueHolder v, short value, boolean expectFailure)210 static void getShort(MethodHandle m, ValueHolder v, short value, boolean expectFailure) 211 throws Throwable { 212 boolean exceptionThrown = false; 213 try { 214 final short got = (v == null) ? (short) m.invokeExact() : (short) m.invokeExact(v); 215 assertTrue(got == value); 216 } 217 catch (WrongMethodTypeException e) { 218 exceptionThrown = true; 219 } 220 assertEquals(expectFailure, exceptionThrown); 221 } 222 getShort(MethodHandle m, short value, boolean expectFailure)223 static void getShort(MethodHandle m, short value, boolean expectFailure) throws Throwable { 224 getShort(m, null, value, expectFailure); 225 } 226 setInt(MethodHandle m, ValueHolder v, int value, boolean expectFailure)227 static void setInt(MethodHandle m, ValueHolder v, int value, boolean expectFailure) 228 throws Throwable { 229 boolean exceptionThrown = false; 230 try { 231 if (v == null) { 232 m.invokeExact(value); 233 } 234 else { 235 m.invokeExact(v, value); 236 } 237 } 238 catch (WrongMethodTypeException e) { 239 exceptionThrown = true; 240 } 241 assertEquals(expectFailure, exceptionThrown); 242 } 243 setInt(MethodHandle m, int value, boolean expectFailure)244 static void setInt(MethodHandle m, int value, boolean expectFailure) throws Throwable { 245 setInt(m, null, value, expectFailure); 246 } 247 getInt(MethodHandle m, ValueHolder v, int value, boolean expectFailure)248 static void getInt(MethodHandle m, ValueHolder v, int value, boolean expectFailure) 249 throws Throwable { 250 boolean exceptionThrown = false; 251 try { 252 final int got = (v == null) ? (int) m.invokeExact() : (int) m.invokeExact(v); 253 assertTrue(got == value); 254 } 255 catch (WrongMethodTypeException e) { 256 exceptionThrown = true; 257 } 258 assertEquals(expectFailure, exceptionThrown); 259 } 260 getInt(MethodHandle m, int value, boolean expectFailure)261 static void getInt(MethodHandle m, int value, boolean expectFailure) throws Throwable { 262 getInt(m, null, value, expectFailure); 263 } 264 setLong(MethodHandle m, ValueHolder v, long value, boolean expectFailure)265 static void setLong(MethodHandle m, ValueHolder v, long value, boolean expectFailure) 266 throws Throwable { 267 boolean exceptionThrown = false; 268 try { 269 if (v == null) { 270 m.invokeExact(value); 271 } 272 else { 273 m.invokeExact(v, value); 274 } 275 } 276 catch (WrongMethodTypeException e) { 277 exceptionThrown = true; 278 } 279 assertEquals(expectFailure, exceptionThrown); 280 } 281 setLong(MethodHandle m, long value, boolean expectFailure)282 static void setLong(MethodHandle m, long value, boolean expectFailure) throws Throwable { 283 setLong(m, null, value, expectFailure); 284 } 285 getLong(MethodHandle m, ValueHolder v, long value, boolean expectFailure)286 static void getLong(MethodHandle m, ValueHolder v, long value, boolean expectFailure) 287 throws Throwable { 288 boolean exceptionThrown = false; 289 try { 290 final long got = (v == null) ? (long) m.invokeExact() : (long) m.invokeExact(v); 291 assertTrue(got == value); 292 } 293 catch (WrongMethodTypeException e) { 294 exceptionThrown = true; 295 } 296 assertEquals(expectFailure, exceptionThrown); 297 } 298 getLong(MethodHandle m, long value, boolean expectFailure)299 static void getLong(MethodHandle m, long value, boolean expectFailure) throws Throwable { 300 getLong(m, null, value, expectFailure); 301 } 302 setFloat(MethodHandle m, ValueHolder v, float value, boolean expectFailure)303 static void setFloat(MethodHandle m, ValueHolder v, float value, boolean expectFailure) 304 throws Throwable { 305 boolean exceptionThrown = false; 306 try { 307 if (v == null) { 308 m.invokeExact(value); 309 } 310 else { 311 m.invokeExact(v, value); 312 } 313 } 314 catch (WrongMethodTypeException e) { 315 exceptionThrown = true; 316 } 317 assertEquals(expectFailure, exceptionThrown); 318 } 319 setFloat(MethodHandle m, float value, boolean expectFailure)320 static void setFloat(MethodHandle m, float value, boolean expectFailure) throws Throwable { 321 setFloat(m, null, value, expectFailure); 322 } 323 getFloat(MethodHandle m, ValueHolder v, float value, boolean expectFailure)324 static void getFloat(MethodHandle m, ValueHolder v, float value, boolean expectFailure) 325 throws Throwable { 326 boolean exceptionThrown = false; 327 try { 328 final float got = (v == null) ? (float) m.invokeExact() : (float) m.invokeExact(v); 329 assertTrue(got == value); 330 } 331 catch (WrongMethodTypeException e) { 332 exceptionThrown = true; 333 } 334 assertEquals(expectFailure, exceptionThrown); 335 } 336 getFloat(MethodHandle m, float value, boolean expectFailure)337 static void getFloat(MethodHandle m, float value, boolean expectFailure) throws Throwable { 338 getFloat(m, null, value, expectFailure); 339 } 340 setDouble(MethodHandle m, ValueHolder v, double value, boolean expectFailure)341 static void setDouble(MethodHandle m, ValueHolder v, double value, boolean expectFailure) 342 throws Throwable { 343 boolean exceptionThrown = false; 344 try { 345 if (v == null) { 346 m.invokeExact(value); 347 } 348 else { 349 m.invokeExact(v, value); 350 } 351 } 352 catch (WrongMethodTypeException e) { 353 exceptionThrown = true; 354 } 355 assertEquals(expectFailure, exceptionThrown); 356 } 357 setDouble(MethodHandle m, double value, boolean expectFailure)358 static void setDouble(MethodHandle m, double value, boolean expectFailure) 359 throws Throwable { 360 setDouble(m, null, value, expectFailure); 361 } 362 getDouble(MethodHandle m, ValueHolder v, double value, boolean expectFailure)363 static void getDouble(MethodHandle m, ValueHolder v, double value, boolean expectFailure) 364 throws Throwable { 365 boolean exceptionThrown = false; 366 try { 367 final double got = (v == null) ? (double) m.invokeExact() : (double) m.invokeExact(v); 368 assertTrue(got == value); 369 } 370 catch (WrongMethodTypeException e) { 371 exceptionThrown = true; 372 } 373 assertEquals(expectFailure, exceptionThrown); 374 } 375 getDouble(MethodHandle m, double value, boolean expectFailure)376 static void getDouble(MethodHandle m, double value, boolean expectFailure) 377 throws Throwable { 378 getDouble(m, null, value, expectFailure); 379 } 380 setString(MethodHandle m, ValueHolder v, String value, boolean expectFailure)381 static void setString(MethodHandle m, ValueHolder v, String value, boolean expectFailure) 382 throws Throwable { 383 boolean exceptionThrown = false; 384 try { 385 if (v == null) { 386 m.invokeExact(value); 387 } 388 else { 389 m.invokeExact(v, value); 390 } 391 } 392 catch (WrongMethodTypeException e) { 393 exceptionThrown = true; 394 } 395 assertEquals(expectFailure, exceptionThrown); 396 } 397 setString(MethodHandle m, String value, boolean expectFailure)398 static void setString(MethodHandle m, String value, boolean expectFailure) 399 throws Throwable { 400 setString(m, null, value, expectFailure); 401 } 402 getString(MethodHandle m, ValueHolder v, String value, boolean expectFailure)403 static void getString(MethodHandle m, ValueHolder v, String value, boolean expectFailure) 404 throws Throwable { 405 boolean exceptionThrown = false; 406 try { 407 final String got = (v == null) ? (String) m.invokeExact() : (String) m.invokeExact(v); 408 assertTrue(got.equals(value)); 409 } 410 catch (WrongMethodTypeException e) { 411 exceptionThrown = true; 412 } 413 assertEquals(expectFailure, exceptionThrown); 414 } 415 getString(MethodHandle m, String value, boolean expectFailure)416 static void getString(MethodHandle m, String value, boolean expectFailure) 417 throws Throwable { 418 getString(m, null, value, expectFailure); 419 } 420 setBoolean(MethodHandle m, ValueHolder v, boolean value, boolean expectFailure)421 static void setBoolean(MethodHandle m, ValueHolder v, boolean value, boolean expectFailure) 422 throws Throwable { 423 boolean exceptionThrown = false; 424 try { 425 if (v == null) { 426 m.invokeExact(value); 427 } 428 else { 429 m.invokeExact(v, value); 430 } 431 } 432 catch (WrongMethodTypeException e) { 433 exceptionThrown = true; 434 } 435 assertEquals(expectFailure, exceptionThrown); 436 } 437 setBoolean(MethodHandle m, boolean value, boolean expectFailure)438 static void setBoolean(MethodHandle m, boolean value, boolean expectFailure) 439 throws Throwable { 440 setBoolean(m, null, value, expectFailure); 441 } 442 getBoolean(MethodHandle m, ValueHolder v, boolean value, boolean expectFailure)443 static void getBoolean(MethodHandle m, ValueHolder v, boolean value, boolean expectFailure) 444 throws Throwable { 445 boolean exceptionThrown = false; 446 try { 447 final boolean got = 448 (v == null) ? (boolean) m.invokeExact() : (boolean) m.invokeExact(v); 449 assertTrue(got == value); 450 } 451 catch (WrongMethodTypeException e) { 452 exceptionThrown = true; 453 } 454 assertEquals(expectFailure, exceptionThrown); 455 } 456 getBoolean(MethodHandle m, boolean value, boolean expectFailure)457 static void getBoolean(MethodHandle m, boolean value, boolean expectFailure) 458 throws Throwable { 459 getBoolean(m, null, value, expectFailure); 460 } 461 resultFor(PrimitiveType actualType, PrimitiveType expectedType, AccessorType actualAccessor, AccessorType expectedAccessor)462 static boolean resultFor(PrimitiveType actualType, PrimitiveType expectedType, 463 AccessorType actualAccessor, 464 AccessorType expectedAccessor) { 465 return (actualType != expectedType) || (actualAccessor != expectedAccessor); 466 } 467 tryAccessor(MethodHandle methodHandle, ValueHolder valueHolder, PrimitiveType primitive, Object value, AccessorType accessor)468 static void tryAccessor(MethodHandle methodHandle, 469 ValueHolder valueHolder, 470 PrimitiveType primitive, 471 Object value, 472 AccessorType accessor) throws Throwable { 473 boolean booleanValue = 474 value instanceof Boolean ? ((Boolean) value).booleanValue() : false; 475 setBoolean(methodHandle, valueHolder, booleanValue, 476 resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.IPUT)); 477 setBoolean(methodHandle, booleanValue, 478 resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.SPUT)); 479 getBoolean(methodHandle, valueHolder, booleanValue, 480 resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.IGET)); 481 getBoolean(methodHandle, booleanValue, 482 resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.SGET)); 483 484 byte byteValue = value instanceof Byte ? ((Byte) value).byteValue() : (byte) 0; 485 setByte(methodHandle, valueHolder, byteValue, 486 resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.IPUT)); 487 setByte(methodHandle, byteValue, 488 resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.SPUT)); 489 getByte(methodHandle, valueHolder, byteValue, 490 resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.IGET)); 491 getByte(methodHandle, byteValue, 492 resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.SGET)); 493 494 char charValue = value instanceof Character ? ((Character) value).charValue() : 'z'; 495 setChar(methodHandle, valueHolder, charValue, 496 resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.IPUT)); 497 setChar(methodHandle, charValue, 498 resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.SPUT)); 499 getChar(methodHandle, valueHolder, charValue, 500 resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.IGET)); 501 getChar(methodHandle, charValue, 502 resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.SGET)); 503 504 short shortValue = value instanceof Short ? ((Short) value).shortValue() : (short) 0; 505 setShort(methodHandle, valueHolder, shortValue, 506 resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.IPUT)); 507 setShort(methodHandle, shortValue, 508 resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.SPUT)); 509 getShort(methodHandle, valueHolder, shortValue, 510 resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.IGET)); 511 getShort(methodHandle, shortValue, 512 resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.SGET)); 513 514 int intValue = value instanceof Integer ? ((Integer) value).intValue() : -1; 515 setInt(methodHandle, valueHolder, intValue, 516 resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.IPUT)); 517 setInt(methodHandle, intValue, 518 resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.SPUT)); 519 getInt(methodHandle, valueHolder, intValue, 520 resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.IGET)); 521 getInt(methodHandle, intValue, 522 resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.SGET)); 523 524 long longValue = value instanceof Long ? ((Long) value).longValue() : (long) -1; 525 setLong(methodHandle, valueHolder, longValue, 526 resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.IPUT)); 527 setLong(methodHandle, longValue, 528 resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.SPUT)); 529 getLong(methodHandle, valueHolder, longValue, 530 resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.IGET)); 531 getLong(methodHandle, longValue, 532 resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.SGET)); 533 534 float floatValue = value instanceof Float ? ((Float) value).floatValue() : -1.0f; 535 setFloat(methodHandle, valueHolder, floatValue, 536 resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.IPUT)); 537 setFloat(methodHandle, floatValue, 538 resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.SPUT)); 539 getFloat(methodHandle, valueHolder, floatValue, 540 resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.IGET)); 541 getFloat(methodHandle, floatValue, 542 resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.SGET)); 543 544 double doubleValue = value instanceof Double ? ((Double) value).doubleValue() : -1.0; 545 setDouble(methodHandle, valueHolder, doubleValue, 546 resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.IPUT)); 547 setDouble(methodHandle, doubleValue, 548 resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.SPUT)); 549 getDouble(methodHandle, valueHolder, doubleValue, 550 resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.IGET)); 551 getDouble(methodHandle, doubleValue, 552 resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.SGET)); 553 554 String stringValue = value instanceof String ? ((String) value) : "No Spock, no"; 555 setString(methodHandle, valueHolder, stringValue, 556 resultFor(primitive, PrimitiveType.String, accessor, AccessorType.IPUT)); 557 setString(methodHandle, stringValue, 558 resultFor(primitive, PrimitiveType.String, accessor, AccessorType.SPUT)); 559 getString(methodHandle, valueHolder, stringValue, 560 resultFor(primitive, PrimitiveType.String, accessor, AccessorType.IGET)); 561 getString(methodHandle, stringValue, 562 resultFor(primitive, PrimitiveType.String, accessor, AccessorType.SGET)); 563 } 564 main()565 public static void main() throws Throwable { 566 ValueHolder valueHolder = new ValueHolder(); 567 MethodHandles.Lookup lookup = MethodHandles.lookup(); 568 569 boolean [] booleans = { false, true, false }; 570 for (boolean b : booleans) { 571 Boolean boxed = new Boolean(b); 572 tryAccessor(lookup.findSetter(ValueHolder.class, "m_z", boolean.class), 573 valueHolder, PrimitiveType.Boolean, boxed, AccessorType.IPUT); 574 tryAccessor(lookup.findGetter(ValueHolder.class, "m_z", boolean.class), 575 valueHolder, PrimitiveType.Boolean, boxed, AccessorType.IGET); 576 assertTrue(valueHolder.m_z == b); 577 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_z", boolean.class), 578 valueHolder, PrimitiveType.Boolean, boxed, AccessorType.SPUT); 579 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_z", boolean.class), 580 valueHolder, PrimitiveType.Boolean, boxed, AccessorType.SGET); 581 assertTrue(ValueHolder.s_z == b); 582 } 583 584 byte [] bytes = { (byte) 0x73, (byte) 0xfe }; 585 for (byte b : bytes) { 586 Byte boxed = new Byte(b); 587 tryAccessor(lookup.findSetter(ValueHolder.class, "m_b", byte.class), 588 valueHolder, PrimitiveType.Byte, boxed, AccessorType.IPUT); 589 tryAccessor(lookup.findGetter(ValueHolder.class, "m_b", byte.class), 590 valueHolder, PrimitiveType.Byte, boxed, AccessorType.IGET); 591 assertTrue(valueHolder.m_b == b); 592 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_b", byte.class), 593 valueHolder, PrimitiveType.Byte, boxed, AccessorType.SPUT); 594 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_b", byte.class), 595 valueHolder, PrimitiveType.Byte, boxed, AccessorType.SGET); 596 assertTrue(ValueHolder.s_b == b); 597 } 598 599 char [] chars = { 'a', 'b', 'c' }; 600 for (char c : chars) { 601 Character boxed = new Character(c); 602 tryAccessor(lookup.findSetter(ValueHolder.class, "m_c", char.class), 603 valueHolder, PrimitiveType.Char, boxed, AccessorType.IPUT); 604 tryAccessor(lookup.findGetter(ValueHolder.class, "m_c", char.class), 605 valueHolder, PrimitiveType.Char, boxed, AccessorType.IGET); 606 assertTrue(valueHolder.m_c == c); 607 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_c", char.class), 608 valueHolder, PrimitiveType.Char, boxed, AccessorType.SPUT); 609 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_c", char.class), 610 valueHolder, PrimitiveType.Char, boxed, AccessorType.SGET); 611 assertTrue(ValueHolder.s_c == c); 612 } 613 614 short [] shorts = { (short) 0x1234, (short) 0x4321 }; 615 for (short s : shorts) { 616 Short boxed = new Short(s); 617 tryAccessor(lookup.findSetter(ValueHolder.class, "m_s", short.class), 618 valueHolder, PrimitiveType.Short, boxed, AccessorType.IPUT); 619 tryAccessor(lookup.findGetter(ValueHolder.class, "m_s", short.class), 620 valueHolder, PrimitiveType.Short, boxed, AccessorType.IGET); 621 assertTrue(valueHolder.m_s == s); 622 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_s", short.class), 623 valueHolder, PrimitiveType.Short, boxed, AccessorType.SPUT); 624 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_s", short.class), 625 valueHolder, PrimitiveType.Short, boxed, AccessorType.SGET); 626 assertTrue(ValueHolder.s_s == s); 627 } 628 629 int [] ints = { -100000000, 10000000 }; 630 for (int i : ints) { 631 Integer boxed = new Integer(i); 632 tryAccessor(lookup.findSetter(ValueHolder.class, "m_i", int.class), 633 valueHolder, PrimitiveType.Int, boxed, AccessorType.IPUT); 634 tryAccessor(lookup.findGetter(ValueHolder.class, "m_i", int.class), 635 valueHolder, PrimitiveType.Int, boxed, AccessorType.IGET); 636 assertTrue(valueHolder.m_i == i); 637 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_i", int.class), 638 valueHolder, PrimitiveType.Int, boxed, AccessorType.SPUT); 639 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_i", int.class), 640 valueHolder, PrimitiveType.Int, boxed, AccessorType.SGET); 641 assertTrue(ValueHolder.s_i == i); 642 } 643 644 float [] floats = { 0.99f, -1.23e-17f }; 645 for (float f : floats) { 646 Float boxed = Float.valueOf(f); 647 tryAccessor(lookup.findSetter(ValueHolder.class, "m_f", float.class), 648 valueHolder, PrimitiveType.Float, boxed, AccessorType.IPUT); 649 tryAccessor(lookup.findGetter(ValueHolder.class, "m_f", float.class), 650 valueHolder, PrimitiveType.Float, boxed, AccessorType.IGET); 651 assertTrue(valueHolder.m_f == f); 652 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_f", float.class), 653 valueHolder, PrimitiveType.Float, boxed, AccessorType.SPUT); 654 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_f", float.class), 655 valueHolder, PrimitiveType.Float, boxed, AccessorType.SGET); 656 assertTrue(ValueHolder.s_f == f); 657 } 658 659 double [] doubles = { 0.44444444444e37, -0.555555555e-37 }; 660 for (double d : doubles) { 661 Double boxed = Double.valueOf(d); 662 tryAccessor(lookup.findSetter(ValueHolder.class, "m_d", double.class), 663 valueHolder, PrimitiveType.Double, boxed, AccessorType.IPUT); 664 tryAccessor(lookup.findGetter(ValueHolder.class, "m_d", double.class), 665 valueHolder, PrimitiveType.Double, boxed, AccessorType.IGET); 666 assertTrue(valueHolder.m_d == d); 667 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_d", double.class), 668 valueHolder, PrimitiveType.Double, boxed, AccessorType.SPUT); 669 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_d", double.class), 670 valueHolder, PrimitiveType.Double, boxed, AccessorType.SGET); 671 assertTrue(ValueHolder.s_d == d); 672 } 673 674 long [] longs = { 0x0123456789abcdefl, 0xfedcba9876543210l }; 675 for (long j : longs) { 676 Long boxed = new Long(j); 677 tryAccessor(lookup.findSetter(ValueHolder.class, "m_j", long.class), 678 valueHolder, PrimitiveType.Long, boxed, AccessorType.IPUT); 679 tryAccessor(lookup.findGetter(ValueHolder.class, "m_j", long.class), 680 valueHolder, PrimitiveType.Long, boxed, AccessorType.IGET); 681 assertTrue(valueHolder.m_j == j); 682 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_j", long.class), 683 valueHolder, PrimitiveType.Long, boxed, AccessorType.SPUT); 684 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_j", long.class), 685 valueHolder, PrimitiveType.Long, boxed, AccessorType.SGET); 686 assertTrue(ValueHolder.s_j == j); 687 } 688 689 String [] strings = { "octopus", "crab" }; 690 for (String s : strings) { 691 tryAccessor(lookup.findSetter(ValueHolder.class, "m_l", String.class), 692 valueHolder, PrimitiveType.String, s, AccessorType.IPUT); 693 tryAccessor(lookup.findGetter(ValueHolder.class, "m_l", String.class), 694 valueHolder, PrimitiveType.String, s, AccessorType.IGET); 695 assertTrue(s.equals(valueHolder.m_l)); 696 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_l", String.class), 697 valueHolder, PrimitiveType.String, s, AccessorType.SPUT); 698 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_l", String.class), 699 valueHolder, PrimitiveType.String, s, AccessorType.SGET); 700 assertTrue(s.equals(ValueHolder.s_l)); 701 } 702 703 System.out.println("Passed MethodHandle.invokeExact() tests for accessors."); 704 } 705 } 706 707 public static class FindAccessorTester extends Tester { main()708 public static void main() throws Throwable { 709 // NB having a static field test here is essential for 710 // this test. MethodHandles need to ensure the class 711 // (ValueHolder) is initialized. This happens in the 712 // invoke-polymorphic dispatch. 713 MethodHandles.Lookup lookup = MethodHandles.lookup(); 714 { 715 MethodHandle mh = lookup.findStaticGetter(ValueHolder.class, "s_fi", int.class); 716 int initialValue = (int) mh.invokeExact(); 717 System.out.println(initialValue); 718 } 719 { 720 MethodHandle mh = lookup.findStaticSetter(ValueHolder.class, "s_i", int.class); 721 mh.invokeExact(0); 722 } 723 try { 724 lookup.findStaticGetter(ValueHolder.class, "s_fi", byte.class); 725 fail(); 726 } catch (NoSuchFieldException expected) {} 727 try { 728 lookup.findGetter(ValueHolder.class, "s_fi", byte.class); 729 fail(); 730 } catch (NoSuchFieldException eexpected) {} 731 try { 732 lookup.findStaticSetter(ValueHolder.class, "s_fi", int.class); 733 fail(); 734 } catch (IllegalAccessException expected) {} 735 736 lookup.findGetter(ValueHolder.class, "m_fi", int.class); 737 try { 738 lookup.findGetter(ValueHolder.class, "m_fi", byte.class); 739 fail(); 740 } catch (NoSuchFieldException expected) {} 741 try { 742 lookup.findStaticGetter(ValueHolder.class, "m_fi", byte.class); 743 fail(); 744 } catch (NoSuchFieldException expected) {} 745 try { 746 lookup.findSetter(ValueHolder.class, "m_fi", int.class); 747 fail(); 748 } catch (IllegalAccessException expected) {} 749 750 System.out.println("Passed MethodHandles.Lookup tests for accessors."); 751 } 752 } 753 754 public static class InvokeTester extends Tester { testStaticGetter()755 private static void testStaticGetter() throws Throwable { 756 MethodHandles.Lookup lookup = MethodHandles.lookup(); 757 MethodHandle h0 = lookup.findStaticGetter(ValueHolder.class, "s_fi", int.class); 758 h0.invoke(); 759 Number t = (Number) h0.invoke(); 760 int u = (int) h0.invoke(); 761 Integer v = (Integer) h0.invoke(); 762 long w = (long) h0.invoke(); 763 try { 764 byte x = (byte) h0.invoke(); 765 fail(); 766 } catch (WrongMethodTypeException expected) {} 767 try { 768 String y = (String) h0.invoke(); 769 fail(); 770 } catch (WrongMethodTypeException expected) {} 771 try { 772 Long z = (Long) h0.invoke(); 773 fail(); 774 } catch (WrongMethodTypeException expected) {} 775 } 776 testMemberGetter()777 private static void testMemberGetter() throws Throwable { 778 ValueHolder valueHolder = new ValueHolder(); 779 MethodHandles.Lookup lookup = MethodHandles.lookup(); 780 MethodHandle h0 = lookup.findGetter(ValueHolder.class, "m_fi", int.class); 781 h0.invoke(valueHolder); 782 Number t = (Number) h0.invoke(valueHolder); 783 int u = (int) h0.invoke(valueHolder); 784 Integer v = (Integer) h0.invoke(valueHolder); 785 long w = (long) h0.invoke(valueHolder); 786 try { 787 byte x = (byte) h0.invoke(valueHolder); 788 fail(); 789 } catch (WrongMethodTypeException expected) {} 790 try { 791 String y = (String) h0.invoke(valueHolder); 792 fail(); 793 } catch (WrongMethodTypeException expected) {} 794 try { 795 Long z = (Long) h0.invoke(valueHolder); 796 fail(); 797 } catch (WrongMethodTypeException expected) {} 798 try { 799 int x = (int) h0.invokeExact((ValueHolder) null); 800 fail(); 801 } catch (NullPointerException expected) {} 802 } 803 getDoubleAsNumber()804 /*package*/ static Number getDoubleAsNumber() { 805 return Double.valueOf(1.4e77); 806 } getFloatAsNumber()807 /*package*/ static Number getFloatAsNumber() { 808 return Float.valueOf(7.77f); 809 } getFloatAsObject()810 /*package*/ static Object getFloatAsObject() { 811 return Float.valueOf(-7.77f); 812 } 813 testMemberSetter()814 private static void testMemberSetter() throws Throwable { 815 ValueHolder valueHolder = new ValueHolder(); 816 MethodHandles.Lookup lookup = MethodHandles.lookup(); 817 MethodHandle h0 = lookup.findSetter(ValueHolder.class, "m_f", float.class); 818 MethodHandle s0 = lookup.findSetter(ValueHolder.class, "m_s", short.class); 819 h0.invoke(valueHolder, 0.22f); 820 h0.invoke(valueHolder, Float.valueOf(1.11f)); 821 Number floatNumber = getFloatAsNumber(); 822 h0.invoke(valueHolder, floatNumber); 823 assertTrue(valueHolder.m_f == floatNumber.floatValue()); 824 Object objNumber = getFloatAsObject(); 825 h0.invoke(valueHolder, objNumber); 826 assertTrue(valueHolder.m_f == ((Float) objNumber).floatValue()); 827 try { 828 h0.invoke(valueHolder, (Float) null); 829 fail(); 830 } catch (NullPointerException expected) {} 831 try { 832 h0.invoke((ValueHolder) null, Float.valueOf(1.0f)); 833 fail(); 834 } catch (NullPointerException expected) {} 835 836 // Test that type conversion checks work on small field types. 837 short temp = (short) s0.invoke(valueHolder, new Byte((byte) 45)); 838 assertTrue(temp == 0); 839 assertTrue(valueHolder.m_s == 45); 840 841 h0.invoke(valueHolder, (byte) 1); 842 h0.invoke(valueHolder, (short) 2); 843 h0.invoke(valueHolder, 3); 844 h0.invoke(valueHolder, 4l); 845 846 assertTrue(null == (Object) h0.invoke(valueHolder, 33)); 847 assertTrue(0.0f == (float) h0.invoke(valueHolder, 33)); 848 assertTrue(0l == (long) h0.invoke(valueHolder, 33)); 849 850 try { 851 h0.invoke(valueHolder, 0.33); 852 fail(); 853 } catch (WrongMethodTypeException expected) {} 854 try { 855 Number doubleNumber = getDoubleAsNumber(); 856 h0.invoke(valueHolder, doubleNumber); 857 fail(); 858 } catch (ClassCastException expected) {} 859 try { 860 Number doubleNumber = null; 861 h0.invoke(valueHolder, doubleNumber); 862 fail(); 863 } catch (NullPointerException expected) {} 864 { 865 // Mismatched return type - float != void 866 float tmp = (float) h0.invoke(valueHolder, 0.45f); 867 assertTrue(tmp == 0.0); 868 } 869 try { 870 h0.invoke(valueHolder, "bam"); 871 fail(); 872 } catch (WrongMethodTypeException expected) {} 873 try { 874 String s = null; 875 h0.invoke(valueHolder, s); 876 fail(); 877 } catch (WrongMethodTypeException expected) {} 878 } 879 testStaticSetter()880 private static void testStaticSetter() throws Throwable { 881 MethodHandles.Lookup lookup = MethodHandles.lookup(); 882 MethodHandle s0 = lookup.findStaticSetter(ValueHolder.class, "s_s", short.class); 883 MethodHandle h0 = lookup.findStaticSetter(ValueHolder.class, "s_f", float.class); 884 h0.invoke(0.22f); 885 h0.invoke(Float.valueOf(1.11f)); 886 Number floatNumber = Float.valueOf(0.88f); 887 h0.invoke(floatNumber); 888 assertTrue(ValueHolder.s_f == floatNumber.floatValue()); 889 890 try { 891 h0.invoke((Float) null); 892 fail(); 893 } catch (NullPointerException expected) {} 894 895 // Test that type conversion checks work on small field types. 896 short temp = (short) s0.invoke(new Byte((byte) 45)); 897 assertTrue(temp == 0); 898 assertTrue(ValueHolder.s_s == 45); 899 900 h0.invoke((byte) 1); 901 h0.invoke((short) 2); 902 h0.invoke(3); 903 h0.invoke(4l); 904 905 assertTrue(null == (Object) h0.invoke(33)); 906 assertTrue(0.0f == (float) h0.invoke(33)); 907 assertTrue(0l == (long) h0.invoke(33)); 908 909 try { 910 h0.invoke(0.33); 911 fail(); 912 } catch (WrongMethodTypeException expected) {} 913 try { 914 h0.invoke(Double.valueOf(0.33)); 915 fail(); 916 } catch (WrongMethodTypeException expected) {} 917 try { 918 Number doubleNumber = getDoubleAsNumber(); 919 h0.invoke(doubleNumber); 920 fail(); 921 } catch (ClassCastException expected) {} 922 try { 923 Number doubleNumber = Double.valueOf(1.01); 924 doubleNumber = (doubleNumber.doubleValue() != 0.1) ? null : doubleNumber; 925 h0.invoke(doubleNumber); 926 fail(); 927 } catch (NullPointerException expected) {} 928 try { 929 // Mismatched return type - float != void 930 float tmp = (float) h0.invoke(0.45f); 931 assertTrue(tmp == 0.0); 932 } catch (Exception e) { fail(); } 933 try { 934 h0.invoke("bam"); 935 fail(); 936 } catch (WrongMethodTypeException expected) {} 937 try { 938 String s = null; 939 h0.invoke(s); 940 fail(); 941 } catch (WrongMethodTypeException expected) {} 942 } 943 main()944 public static void main() throws Throwable{ 945 testStaticGetter(); 946 testMemberGetter(); 947 testStaticSetter(); 948 testMemberSetter(); 949 System.out.println("Passed MethodHandle.invoke() tests for accessors."); 950 } 951 } 952 953 public static class UnreflectTester extends Tester { main()954 public static void main() throws Throwable { 955 ValueHolder v = new ValueHolder(); 956 { 957 // public field test 958 Field f = ValueHolder.class.getDeclaredField("m_c"); 959 MethodHandles.lookup().unreflectSetter(f).invokeExact(v, 'z'); 960 assertEquals('z', (char) MethodHandles.lookup().unreflectGetter(f).invokeExact(v)); 961 MethodHandles.lookup().unreflectSetter(f).invokeExact(v, 'A'); 962 assertEquals('A', (char) MethodHandles.lookup().unreflectGetter(f).invokeExact(v)); 963 } 964 if (DALVIK_RUN) { 965 // public static final field test 966 // for JVM it is not possible to get the unreflected setter for a static final 967 // field, see b/242985782 968 Field f = ValueHolder.class.getDeclaredField("s_fi"); 969 try { 970 MethodHandles.lookup().unreflectSetter(f); 971 fail(); 972 } catch (IllegalAccessException expected) {} 973 MethodHandles.lookup().unreflectGetter(f); 974 f.setAccessible(true); 975 int savedValue = (int) MethodHandles.lookup().unreflectGetter(f).invokeExact(); 976 int newValue = savedValue + 1; 977 MethodHandles.lookup().unreflectSetter(f).invokeExact(newValue); 978 assertEquals(newValue, (int) MethodHandles.lookup().unreflectGetter(f).invokeExact() 979 ); 980 MethodHandles.lookup().unreflectSetter(f).invokeExact(savedValue); 981 assertEquals(savedValue, (int) MethodHandles.lookup().unreflectGetter(f).invokeExact() 982 ); 983 f.setAccessible(false); 984 try { 985 MethodHandles.lookup().unreflectSetter(f); 986 fail(); 987 } catch (IllegalAccessException expected) {} 988 MethodHandles.lookup().unreflectGetter(f); 989 } 990 { 991 // private field test 992 Field f = ValueHolder.class.getDeclaredField("m_pz"); 993 try { 994 MethodHandle mh = MethodHandles.lookup().unreflectSetter(f); 995 fail(); 996 } catch (IllegalAccessException expected) {} 997 try { 998 MethodHandle mh = MethodHandles.lookup().unreflectGetter(f); 999 fail(); 1000 } catch (IllegalAccessException expected) {} 1001 f.setAccessible(true); 1002 MethodHandles.lookup().unreflectSetter(f).invokeExact(v, true); 1003 assertEquals(true, (boolean) MethodHandles.lookup().unreflectGetter(f).invokeExact(v) 1004 ); 1005 MethodHandles.lookup().unreflectSetter(f).invokeExact(v, false); 1006 assertEquals(false, (boolean) MethodHandles.lookup().unreflectGetter(f).invokeExact(v) 1007 ); 1008 f.setAccessible(false); 1009 try { 1010 MethodHandle mh = MethodHandles.lookup().unreflectGetter(f); 1011 fail(); 1012 } catch (IllegalAccessException expected) {} 1013 try { 1014 MethodHandle mh = MethodHandles.lookup().unreflectSetter(f); 1015 fail(); 1016 } catch (IllegalAccessException expected) {} 1017 } 1018 if (DALVIK_RUN) { 1019 // private static final field test 1020 // for JVM it is not possible to get the unreflected setter for a static final 1021 // field, see b/242985782 1022 Field f = ValueHolder.class.getDeclaredField("s_fz"); // private static final field 1023 try { 1024 MethodHandles.lookup().unreflectSetter(f); 1025 fail(); 1026 } catch (IllegalAccessException expected) {} 1027 try { 1028 MethodHandles.lookup().unreflectGetter(f); 1029 fail(); 1030 } catch (IllegalAccessException expected) {} 1031 f.setAccessible(true); 1032 // Setter is okay despite being final because field isAccessible(). 1033 MethodHandles.lookup().unreflectSetter(f).invokeExact(false); 1034 assertEquals(false, (boolean) MethodHandles.lookup().unreflectGetter(f).invokeExact() 1035 ); 1036 MethodHandles.lookup().unreflectSetter(f).invokeExact(true); 1037 assertEquals(true, (boolean) MethodHandles.lookup().unreflectGetter(f).invokeExact() 1038 ); 1039 f.setAccessible(false); 1040 try { 1041 MethodHandles.lookup().unreflectSetter(f); 1042 fail(); 1043 } catch (IllegalAccessException expected) {} 1044 try { 1045 MethodHandles.lookup().unreflectGetter(f); 1046 fail(); 1047 } catch (IllegalAccessException expected) {} 1048 } 1049 System.out.println("Passed MethodHandles.unreflect(Field) tests."); 1050 } 1051 } 1052 main(String[] args)1053 public static void main(String[] args) throws Throwable { 1054 // FindAccessor test should be the first test class in this 1055 // file to ensure class initialization test is run. 1056 FindAccessorTester.main(); 1057 InvokeExactTester.main(); 1058 InvokeTester.main(); 1059 UnreflectTester.main(); 1060 } 1061 } 1062