1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 8173898 27 * @summary Basic test for checking filtering of reflection frames 28 * @run testng ReflectionFrames 29 */ 30 31 package test.java.lang.StackWalker; 32 33 import java.lang.StackWalker.StackFrame; 34 import java.lang.reflect.Constructor; 35 import java.lang.reflect.Method; 36 import java.lang.invoke.MethodHandle; 37 import java.lang.invoke.MethodHandles; 38 import java.lang.invoke.MethodHandles.Lookup; 39 import java.lang.invoke.MethodType; 40 import java.util.EnumSet; 41 import java.util.List; 42 import java.util.function.Supplier; 43 import java.util.stream.Collectors; 44 import java.util.stream.Stream; 45 import static java.lang.StackWalker.Option.*; 46 47 import org.testng.annotations.DataProvider; 48 import org.testng.annotations.Test; 49 import static org.testng.Assert.*; 50 51 public class ReflectionFrames { 52 final static boolean verbose = false; 53 // Android-changed: libcore has different internal implementation for reflection. 54 // final static Class<?> REFLECT_ACCESS = findClass("java.lang.reflect.ReflectAccess"); 55 // final static Class<?> REFLECTION_FACTORY = findClass("jdk.internal.reflect.ReflectionFactory"); 56 final static Class<?> REFLECT_ACCESS = findClass("java.lang.Class"); 57 findClass(String cn)58 private static Class<?> findClass(String cn) { 59 try { 60 return Class.forName(cn); 61 } catch (ClassNotFoundException e) { 62 throw new AssertionError(e); 63 } 64 } 65 66 /** 67 * This test invokes new StackInspector() directly from 68 * the caller StackInspector.Caller.create method. 69 * It checks that the caller is StackInspector.Caller. 70 * It also checks the expected frames collected 71 * by walking the stack from the default StackInspector() 72 * constructor. 73 * This is done twice, once using a default StackWalker 74 * that hides reflection frames, once using a StackWalker 75 * configured to show reflection frames. 76 */ 77 @Test testNewStackInspector()78 public static void testNewStackInspector() throws Exception { 79 // Sets the default walker which hides reflection 80 // frames. 81 StackInspector.walker.set(StackInspector.walkerHide); 82 83 // Calls the StackInspector.create method through reflection 84 // and check the frames collected in the StackInspector 85 // default constructor. 86 // The create method invokes new StackInspector() directly. 87 // No reflection frame should appear. 88 System.out.println("testNewStackInspector: create"); 89 90 StackInspector obj = ((StackInspector)StackInspector.Caller.class 91 .getMethod("create", How.class) 92 .invoke(null, How.NEW)); 93 assertEquals(obj.collectedFrames, 94 List.of(StackInspector.class.getName() 95 +"::<init>", 96 StackInspector.Caller.class.getName() 97 +"::create", 98 ReflectionFrames.class.getName() 99 +"::testNewStackInspector")); 100 assertEquals(obj.cls, StackInspector.Caller.class); 101 assertEquals(obj.filtered, 0); 102 103 // Calls the StackInspector.reflect method through reflection 104 // and check the frames collected in the StackInspector 105 // default constructor. 106 // The reflect method invokes the create method through 107 // reflection. 108 // The create method invokes new StackInspector() directly. 109 // No reflection frame should appear. 110 System.out.println("testNewStackInspector: reflect"); 111 112 obj = ((StackInspector)StackInspector.Caller.class 113 .getMethod("reflect", How.class) 114 .invoke(null, How.NEW)); 115 assertEquals(obj.collectedFrames, 116 List.of(StackInspector.class.getName() 117 +"::<init>", 118 StackInspector.Caller.class.getName() 119 +"::create", 120 StackInspector.Caller.class.getName() 121 +"::reflect", 122 ReflectionFrames.class.getName() 123 +"::testNewStackInspector")); 124 assertEquals(obj.cls, StackInspector.Caller.class); 125 assertEquals(obj.filtered, 0); 126 127 // Calls the StackInspector.handle method through reflection 128 // and check the frames collected in the StackInspector 129 // default constructor. 130 // The handle method invokes the create method using 131 // a MethodHandle. 132 // The create method invokes new StackInspector() directly. 133 // No reflection frame should appear. 134 System.out.println("testNewStackInspector: handle"); 135 136 obj = ((StackInspector)StackInspector.Caller.class 137 .getMethod("handle", How.class) 138 .invoke(null, How.NEW)); 139 assertEquals(obj.collectedFrames, 140 List.of(StackInspector.class.getName() 141 +"::<init>", 142 StackInspector.Caller.class.getName() 143 +"::create", 144 StackInspector.Caller.class.getName() 145 +"::handle", 146 ReflectionFrames.class.getName() 147 +"::testNewStackInspector")); 148 assertEquals(obj.cls, StackInspector.Caller.class); 149 assertEquals(obj.filtered, 0); 150 151 // Sets a non-default walker configured to show 152 // reflection frames 153 StackInspector.walker.set(StackInspector.walkerShow); 154 155 // Calls the StackInspector.create method through reflection 156 // and check the frames collected in the StackInspector 157 // default constructor. 158 // The create method invokes new StackInspector() directly. 159 // We should see all reflection frames, except the 160 // jdk.internal.reflect frames which we are filtering 161 // out in StackInspector::filter. 162 System.out.println("testNewStackInspector: create: show reflect"); 163 164 obj = ((StackInspector)StackInspector.Caller.class 165 .getMethod("create", How.class) 166 .invoke(null, How.NEW)); 167 assertEquals(obj.collectedFrames, 168 List.of(StackInspector.class.getName() 169 +"::<init>", 170 StackInspector.Caller.class.getName() 171 +"::create", 172 Method.class.getName() 173 +"::invoke", 174 ReflectionFrames.class.getName() 175 +"::testNewStackInspector")); 176 assertEquals(obj.cls, StackInspector.Caller.class); 177 // Android-changed: libcore uses very little of jdk.internal.reflect. 178 // assertNotEquals(obj.filtered, 0); 179 180 // Calls the StackInspector.reflect method through reflection 181 // and check the frames collected in the StackInspector 182 // default constructor. 183 // The reflect method invokes the create method through 184 // reflection. 185 // The create method invokes new StackInspector() directly. 186 // We should see all reflection frames, except the 187 // jdk.internal.reflect frames which we are filtering 188 // out in StackInspector::filter. 189 System.out.println("testNewStackInspector: reflect: show reflect"); 190 191 obj = ((StackInspector)StackInspector.Caller.class 192 .getMethod("reflect", How.class) 193 .invoke(null, How.NEW)); 194 assertEquals(obj.collectedFrames, 195 List.of(StackInspector.class.getName() 196 +"::<init>", 197 StackInspector.Caller.class.getName() 198 +"::create", 199 Method.class.getName() 200 +"::invoke", 201 StackInspector.Caller.class.getName() 202 +"::reflect", 203 Method.class.getName() 204 +"::invoke", 205 ReflectionFrames.class.getName() 206 +"::testNewStackInspector")); 207 assertEquals(obj.cls, StackInspector.Caller.class); 208 // Android-changed: libcore uses very little of jdk.internal.reflect. 209 // assertNotEquals(obj.filtered, 0); 210 211 // Calls the StackInspector.handle method through reflection 212 // and check the frames collected in the StackInspector 213 // default constructor. 214 // The handle method invokes the create method using 215 // MethodHandle. 216 // The create method invokes new StackInspector() directly. 217 // We should see all reflection frames, except the 218 // jdk.internal.reflect frames which we are filtering 219 // out in StackInspector::filter. 220 System.out.println("testNewStackInspector: handle: show reflect"); 221 222 obj = ((StackInspector)StackInspector.Caller.class 223 .getMethod("handle", How.class) 224 .invoke(null, How.NEW)); 225 assertEquals(obj.collectedFrames, 226 List.of(StackInspector.class.getName() 227 +"::<init>", 228 StackInspector.Caller.class.getName() 229 +"::create", 230 // MethodHandle::invoke remains hidden 231 StackInspector.Caller.class.getName() 232 +"::handle", 233 Method.class.getName() 234 +"::invoke", 235 ReflectionFrames.class.getName() 236 +"::testNewStackInspector")); 237 assertEquals(obj.cls, StackInspector.Caller.class); 238 // Android-changed: libcore uses very little of jdk.internal.reflect. 239 // assertNotEquals(obj.filtered, 0); 240 } 241 242 /** 243 * This test invokes Constructor.newInstance() from 244 * the caller StackInspector.Caller.create method. 245 * It checks that the caller is StackInspector.Caller. 246 * It also checks the expected frames collected 247 * by walking the stack from the default StackInspector() 248 * constructor. 249 * This is done twice, once using a default StackWalker 250 * that hides reflection frames, once using a StackWalker 251 * configured to show reflection frames. 252 */ 253 @Test testConstructor()254 public static void testConstructor() throws Exception { 255 // Sets the default walker which hides reflection 256 // frames. 257 StackInspector.walker.set(StackInspector.walkerHide); 258 259 // Calls the StackInspector.create method through reflection 260 // and check the frames collected in the StackInspector 261 // default constructor. 262 // The create method invokes Constructor.newInstance(). 263 // No reflection frame should appear. 264 System.out.println("testConstructor: create"); 265 266 StackInspector obj = ((StackInspector)StackInspector.Caller.class 267 .getMethod("create", How.class) 268 .invoke(null, How.CONSTRUCTOR)); 269 assertEquals(obj.collectedFrames, 270 List.of(StackInspector.class.getName() 271 +"::<init>", 272 StackInspector.Caller.class.getName() 273 +"::create", 274 ReflectionFrames.class.getName() 275 +"::testConstructor")); 276 assertEquals(obj.cls, StackInspector.Caller.class); 277 assertEquals(obj.filtered, 0); 278 279 // Calls the StackInspector.reflect method through reflection 280 // and check the frames collected in the StackInspector 281 // default constructor. 282 // The reflect method invokes the create method through 283 // reflection. 284 // The create method invokes Constructor.newInstance(). 285 // No reflection frame should appear. 286 System.out.println("testConstructor: reflect"); 287 288 obj = ((StackInspector)StackInspector.Caller.class 289 .getMethod("reflect", How.class) 290 .invoke(null, How.CONSTRUCTOR)); 291 assertEquals(obj.collectedFrames, 292 List.of(StackInspector.class.getName() 293 +"::<init>", 294 StackInspector.Caller.class.getName() 295 +"::create", 296 StackInspector.Caller.class.getName() 297 +"::reflect", 298 ReflectionFrames.class.getName() 299 +"::testConstructor")); 300 assertEquals(obj.cls, StackInspector.Caller.class); 301 assertEquals(obj.filtered, 0); 302 303 // Calls the StackInspector.handle method through reflection 304 // and check the frames collected in the StackInspector 305 // default constructor. 306 // The handle method invokes the create method using 307 // MethodHandle. 308 // The create method invokes Constructor.newInstance(). 309 // No reflection frame should appear. 310 System.out.println("testConstructor: handle"); 311 312 obj = ((StackInspector)StackInspector.Caller.class 313 .getMethod("handle", How.class) 314 .invoke(null, How.CONSTRUCTOR)); 315 assertEquals(obj.collectedFrames, 316 List.of(StackInspector.class.getName() 317 +"::<init>", 318 StackInspector.Caller.class.getName() 319 +"::create", 320 StackInspector.Caller.class.getName() 321 +"::handle", 322 ReflectionFrames.class.getName() 323 +"::testConstructor")); 324 assertEquals(obj.cls, StackInspector.Caller.class); 325 assertEquals(obj.filtered, 0); 326 327 // Sets a non-default walker configured to show 328 // reflection frames 329 StackInspector.walker.set(StackInspector.walkerShow); 330 331 // Calls the StackInspector.create method through reflection 332 // and check the frames collected in the StackInspector 333 // default constructor. 334 // The create method invokes Constructor.newInstance(). 335 // We should see all reflection frames, except the 336 // jdk.internal.reflect frames which we are filtering 337 // out in StackInspector::filter. 338 System.out.println("testConstructor: create: show reflect"); 339 340 obj = ((StackInspector)StackInspector.Caller.class 341 .getMethod("create", How.class) 342 .invoke(null, How.CONSTRUCTOR)); 343 assertEquals(obj.collectedFrames, 344 List.of(StackInspector.class.getName() 345 +"::<init>", 346 Constructor.class.getName() 347 // Android-changed: libcore internal implementation is different. 348 // +"::newInstanceWithCaller", 349 +"::newInstance0", 350 Constructor.class.getName() 351 +"::newInstance", 352 StackInspector.Caller.class.getName() 353 +"::create", 354 Method.class.getName() 355 +"::invoke", 356 ReflectionFrames.class.getName() 357 +"::testConstructor")); 358 assertEquals(obj.cls, StackInspector.Caller.class); 359 // Android-changed: libcore uses very little of jdk.internal.reflect. 360 // assertNotEquals(obj.filtered, 0); 361 362 // Calls the StackInspector.reflect method through reflection 363 // and check the frames collected in the StackInspector 364 // default constructor. 365 // The reflect method invokes the create method through 366 // reflection. 367 // The create method invokes Constructor.newInstance(). 368 // We should see all reflection frames, except the 369 // jdk.internal.reflect frames which we are filtering 370 // out in StackInspector::filter. 371 System.out.println("testConstructor: reflect: show reflect"); 372 373 obj = ((StackInspector)StackInspector.Caller.class 374 .getMethod("reflect", How.class) 375 .invoke(null, How.CONSTRUCTOR)); 376 assertEquals(obj.collectedFrames, 377 List.of(StackInspector.class.getName() 378 +"::<init>", 379 Constructor.class.getName() 380 // Android-changed: libcore internal implementation is different. 381 // +"::newInstanceWithCaller", 382 +"::newInstance0", 383 Constructor.class.getName() 384 +"::newInstance", 385 StackInspector.Caller.class.getName() 386 +"::create", 387 Method.class.getName() 388 +"::invoke", 389 StackInspector.Caller.class.getName() 390 +"::reflect", 391 Method.class.getName() 392 +"::invoke", 393 ReflectionFrames.class.getName() 394 +"::testConstructor")); 395 assertEquals(obj.cls, StackInspector.Caller.class); 396 // Android-changed: libcore uses very little of jdk.internal.reflect. 397 // assertNotEquals(obj.filtered, 0); 398 399 // Calls the StackInspector.handle method through reflection 400 // and check the frames collected in the StackInspector 401 // default constructor. 402 // The handle method invokes the create method using 403 // MethodHandle. 404 // The create method invokes Constructor.newInstance(). 405 // We should see all reflection frames, except the 406 // jdk.internal.reflect frames which we are filtering 407 // out in StackInspector::filter. 408 System.out.println("testConstructor: handle: show reflect"); 409 410 obj = ((StackInspector)StackInspector.Caller.class 411 .getMethod("handle", How.class) 412 .invoke(null, How.CONSTRUCTOR)); 413 assertEquals(obj.collectedFrames, 414 List.of(StackInspector.class.getName() 415 +"::<init>", 416 Constructor.class.getName() 417 // Android-changed: libcore internal implementation is different. 418 // +"::newInstanceWithCaller", 419 +"::newInstance0", 420 Constructor.class.getName() 421 +"::newInstance", 422 StackInspector.Caller.class.getName() 423 +"::create", 424 // MethodHandle::invoke remains hidden 425 StackInspector.Caller.class.getName() 426 +"::handle", 427 Method.class.getName() 428 +"::invoke", 429 ReflectionFrames.class.getName() 430 +"::testConstructor")); 431 assertEquals(obj.cls, StackInspector.Caller.class); 432 // Android-changed: libcore uses very little of jdk.internal.reflect. 433 // assertNotEquals(obj.filtered, 0); 434 } 435 436 /** 437 * This test invokes StackInspector.class.newInstance() from 438 * the caller StackInspector.Caller.create method. Because 439 * Class.newInstance() is not considered as a 440 * reflection frame, the the caller returned by 441 * getCallerClass() should appear to be java.lang.Class 442 * and not StackInspector.Caller. 443 * It also checks the expected frames collected 444 * by walking the stack from the default StackInspector() 445 * constructor. 446 * This is done twice, once using a default StackWalker 447 * that hides reflection frames, once using a StackWalker 448 * configured to show reflection frames. 449 */ 450 @Test testNewInstance()451 public static void testNewInstance() throws Exception { 452 // Sets the default walker which hides reflection 453 // frames. 454 StackInspector.walker.set(StackInspector.walkerHide); 455 456 // Calls the StackInspector.create method through reflection 457 // and check the frames collected in the StackInspector 458 // default constructor. 459 // The create method invokes StackInspector.class.newInstance(). 460 // No reflection frame should appear, except 461 // Class::newInstance which is not considered as 462 // a reflection frame. 463 System.out.println("testNewInstance: create"); 464 465 StackInspector obj = ((StackInspector)StackInspector.Caller.class 466 .getMethod("create", How.class) 467 .invoke(null, How.CLASS)); 468 assertEquals(obj.collectedFrames, 469 List.of(StackInspector.class.getName() 470 +"::<init>", 471 // Android-changed: libcore internal implementation is different. 472 // REFLECT_ACCESS.getName() 473 // +"::newInstance", 474 // REFLECTION_FACTORY.getName() 475 // +"::newInstance", 476 Class.class.getName() 477 +"::newInstance", 478 StackInspector.Caller.class.getName() 479 +"::create", 480 ReflectionFrames.class.getName() 481 +"::testNewInstance")); 482 // Because implementation frames are not filtered, then the 483 // caller is ReflectAccess.class 484 assertEquals(obj.cls, REFLECT_ACCESS); 485 assertEquals(obj.filtered, 0); 486 487 // Calls the StackInspector.reflect method through reflection 488 // and check the frames collected in the StackInspector 489 // default constructor. 490 // The reflect method invokes the create method through 491 // reflection. 492 // The create method invokes StackInspector.class.newInstance(). 493 // No reflection frame should appear, except 494 // Class::newInstance which is not considered as 495 // a reflection frame. 496 System.out.println("testNewInstance: reflect"); 497 498 obj = ((StackInspector)StackInspector.Caller.class 499 .getMethod("reflect", How.class) 500 .invoke(null, How.CLASS)); 501 assertEquals(obj.collectedFrames, 502 List.of(StackInspector.class.getName() 503 +"::<init>", 504 // Android-changed: libcore internal implementation is different. 505 // REFLECT_ACCESS.getName() 506 // +"::newInstance", 507 // REFLECTION_FACTORY.getName() 508 // +"::newInstance", 509 Class.class.getName() 510 +"::newInstance", 511 StackInspector.Caller.class.getName() 512 +"::create", 513 StackInspector.Caller.class.getName() 514 +"::reflect", 515 ReflectionFrames.class.getName() 516 +"::testNewInstance")); 517 518 // Because implementation frames are not filtered, then the 519 // caller is ReflectAccess.class 520 assertEquals(obj.cls, REFLECT_ACCESS); 521 assertEquals(obj.filtered, 0); 522 523 // Calls the StackInspector.handle method through reflection 524 // and check the frames collected in the StackInspector 525 // default constructor. 526 // The handle method invokes the create method using 527 // reflection. 528 // The create method invokes StackInspector.class.newInstance(). 529 // No reflection frame should appear, except 530 // Class::newInstance which is not considered as 531 // a reflection frame. 532 System.out.println("testNewInstance: handle"); 533 534 obj = ((StackInspector)StackInspector.Caller.class 535 .getMethod("handle", How.class) 536 .invoke(null, How.CLASS)); 537 assertEquals(obj.collectedFrames, 538 List.of(StackInspector.class.getName() 539 +"::<init>", 540 // Android-changed: libcore internal implementation is different. 541 // REFLECT_ACCESS.getName() 542 // +"::newInstance", 543 // REFLECTION_FACTORY.getName() 544 // +"::newInstance", 545 Class.class.getName() 546 +"::newInstance", 547 StackInspector.Caller.class.getName() 548 +"::create", 549 StackInspector.Caller.class.getName() 550 +"::handle", 551 ReflectionFrames.class.getName() 552 +"::testNewInstance")); 553 554 // Because implementation frames are not filtered, then the 555 // caller is ReflectAccess.class 556 assertEquals(obj.cls, REFLECT_ACCESS); 557 assertEquals(obj.filtered, 0); 558 559 // Sets a non-default walker configured to show 560 // reflection frames 561 StackInspector.walker.set(StackInspector.walkerShow); 562 563 // Calls the StackInspector.create method through reflection 564 // and check the frames collected in the StackInspector 565 // default constructor. 566 // The create method invokes StackInspector.class.newInstance(). 567 // We should see all reflection frames, except the 568 // jdk.internal.reflect frames which we are filtering 569 // out in StackInspector::filter. 570 System.out.println("testNewInstance: create: show reflect"); 571 572 obj = ((StackInspector)StackInspector.Caller.class 573 .getMethod("create", How.class) 574 .invoke(null, How.CLASS)); 575 assertEquals(obj.collectedFrames, 576 List.of(StackInspector.class.getName() 577 +"::<init>", 578 // Android-changed: libcore internal implementation is different. 579 // Constructor.class.getName() 580 // +"::newInstanceWithCaller", 581 // REFLECT_ACCESS.getName() 582 // +"::newInstance", 583 Class.class.getName() 584 +"::newInstance", 585 StackInspector.Caller.class.getName() 586 +"::create", 587 Method.class.getName() 588 +"::invoke", 589 ReflectionFrames.class.getName() 590 +"::testNewInstance")); 591 // Because implementation frames are not filtered, then the 592 // caller is ReflectAccess.class 593 assertEquals(obj.cls, REFLECT_ACCESS); 594 // Android-changed: libcore uses very little of jdk.internal.reflect. 595 // assertNotEquals(obj.filtered, 0); 596 597 // Calls the StackInspector.reflect method through reflection 598 // and check the frames collected in the StackInspector 599 // default constructor. 600 // The reflect method invokes the create method through 601 // reflection. 602 // The create method invokes StackInspector.class.newInstance(). 603 // We should see all reflection frames, except the 604 // jdk.internal.reflect frames which we are filtering 605 // out in StackInspector::filter. 606 System.out.println("testNewInstance: reflect: show reflect"); 607 608 obj = ((StackInspector)StackInspector.Caller.class 609 .getMethod("reflect", How.class) 610 .invoke(null, How.CLASS)); 611 System.out.println(obj.collectedFrames); 612 assertEquals(obj.collectedFrames, 613 List.of(StackInspector.class.getName() 614 +"::<init>", 615 // Android-changed: libcore internal implementation is different. 616 // Constructor.class.getName() 617 // +"::newInstanceWithCaller", 618 // REFLECT_ACCESS.getName() 619 // +"::newInstance", 620 Class.class.getName() 621 +"::newInstance", 622 StackInspector.Caller.class.getName() 623 +"::create", 624 Method.class.getName() 625 +"::invoke", 626 StackInspector.Caller.class.getName() 627 +"::reflect", 628 Method.class.getName() 629 +"::invoke", 630 ReflectionFrames.class.getName() 631 +"::testNewInstance")); 632 633 // Because implementation frames are not filtered, then the 634 // caller is ReflectAccess.class 635 assertEquals(obj.cls, REFLECT_ACCESS); 636 // Android-changed: libcore uses very little of jdk.internal.reflect. 637 // assertNotEquals(obj.filtered, 0); 638 639 // Calls the StackInspector.handle method through reflection 640 // and check the frames collected in the StackInspector 641 // default constructor. 642 // The handle method invokes the create method using 643 // MethodHandle. 644 // The create method invokes StackInspector.class.newInstance(). 645 // We should see all reflection frames, except the 646 // jdk.internal.reflect frames which we are filtering 647 // out in StackInspector::filter. 648 System.out.println("testNewInstance: handle: show reflect"); 649 650 obj = ((StackInspector)StackInspector.Caller.class 651 .getMethod("handle", How.class) 652 .invoke(null, How.CLASS)); 653 assertEquals(obj.collectedFrames, 654 List.of(StackInspector.class.getName() 655 +"::<init>", 656 // Android-changed: libcore internal implementation is different. 657 // Constructor.class.getName() 658 // +"::newInstanceWithCaller", 659 // REFLECT_ACCESS.getName() 660 // +"::newInstance", 661 Class.class.getName() 662 +"::newInstance", 663 StackInspector.Caller.class.getName() 664 +"::create", 665 // MethodHandle::invoke remains hidden 666 StackInspector.Caller.class.getName() 667 +"::handle", 668 Method.class.getName() 669 +"::invoke", 670 ReflectionFrames.class.getName() 671 +"::testNewInstance")); 672 673 // Because implementation frames are not filtered, then the 674 // caller is ReflectAccess.class 675 assertEquals(obj.cls, REFLECT_ACCESS); 676 // Android-changed: libcore uses very little of jdk.internal.reflect. 677 // assertNotEquals(obj.filtered, 0); 678 } 679 680 @Test testGetCaller()681 public static void testGetCaller() throws Exception { 682 // Sets the default walker which hides reflection 683 // frames. 684 StackInspector.walker.set(StackInspector.walkerHide); 685 686 assertEquals(StackInspector.getCaller(), ReflectionFrames.class); 687 assertEquals(StackInspector.class.getMethod("getCaller").invoke(null), 688 ReflectionFrames.class); 689 690 // Sets a non-default walker configured to show 691 // reflection frames 692 StackInspector.walker.set(StackInspector.walkerShow); 693 694 assertEquals(StackInspector.getCaller(), ReflectionFrames.class); 695 assertEquals(StackInspector.class.getMethod("getCaller").invoke(null), 696 ReflectionFrames.class); 697 } 698 699 @Test testReflectCaller()700 public static void testReflectCaller() throws Exception { 701 // Sets the default walker which hides reflection 702 // frames. 703 StackInspector.walker.set(StackInspector.walkerHide); 704 705 assertEquals(StackInspector.reflectCaller(), ReflectionFrames.class); 706 assertEquals(StackInspector.class.getMethod("reflectCaller").invoke(null), 707 ReflectionFrames.class); 708 709 // Sets a non-default walker configured to show 710 // reflection frames 711 StackInspector.walker.set(StackInspector.walkerShow); 712 713 assertEquals(StackInspector.reflectCaller(), ReflectionFrames.class); 714 assertEquals(StackInspector.class.getMethod("reflectCaller").invoke(null), 715 ReflectionFrames.class); 716 } 717 718 // Android-changed: Android desugars lambda and thus the caller is different. 719 @Test(enabled = false) testSupplyCaller()720 public static void testSupplyCaller() throws Exception { 721 // Sets the default walker which hides reflection 722 // frames. 723 StackInspector.walker.set(StackInspector.walkerHide); 724 725 assertEquals(StackInspector.supplyCaller(), ReflectionFrames.class); 726 assertEquals(StackInspector.class.getMethod("supplyCaller").invoke(null), 727 ReflectionFrames.class); 728 729 // Sets a non-default walker configured to show 730 // reflection frames 731 StackInspector.walker.set(StackInspector.walkerShow); 732 733 assertEquals(StackInspector.supplyCaller(), ReflectionFrames.class); 734 assertEquals(StackInspector.class.getMethod("supplyCaller").invoke(null), 735 ReflectionFrames.class); 736 } 737 738 @Test testHandleCaller()739 public static void testHandleCaller() throws Exception { 740 // Sets the default walker which hides reflection 741 // frames. 742 StackInspector.walker.set(StackInspector.walkerHide); 743 744 assertEquals(StackInspector.handleCaller(), ReflectionFrames.class); 745 assertEquals(StackInspector.class.getMethod("handleCaller").invoke(null), 746 ReflectionFrames.class); 747 748 // Sets a non-default walker configured to show 749 // reflection frames 750 StackInspector.walker.set(StackInspector.walkerShow); 751 752 assertEquals(StackInspector.handleCaller(), ReflectionFrames.class); 753 assertEquals(StackInspector.class.getMethod("handleCaller").invoke(null), 754 ReflectionFrames.class); 755 } 756 757 static enum How { NEW, CONSTRUCTOR, CLASS}; 758 759 /** 760 * An object that collect stack frames by walking the stack 761 * (and calling getCallerClass()) from within its constructor. 762 * For the purpose of this test, StackInspector objects are 763 * always created from the nested StackInspector.Caller class, 764 * which should therefore appear as the caller of the 765 * StackInspector constructor. 766 */ 767 static class StackInspector { 768 static final StackWalker walkerHide = 769 StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); 770 static final StackWalker walkerShow = 771 StackWalker.getInstance(EnumSet.of( 772 StackWalker.Option.RETAIN_CLASS_REFERENCE, 773 StackWalker.Option.SHOW_REFLECT_FRAMES)); 774 final static ThreadLocal<StackWalker> walker = new ThreadLocal<>() { 775 protected StackWalker initialValue() { 776 return walkerHide; 777 } 778 }; 779 780 List<String> collectedFrames; 781 Class<?> cls = null; 782 boolean stop; 783 int filtered; 784 final boolean filterImplFrames; 785 StackInspector()786 public StackInspector() { 787 stop = false; 788 // if reflection frames are not hidden, we want to 789 // filter implementation frames before collecting 790 // to avoid depending on internal details. 791 filterImplFrames = walker.get() == walkerShow; 792 collectedFrames = walker.get().walk(this::parse); 793 cls = walker.get().getCallerClass(); 794 } 795 collectedFrames()796 public List<String> collectedFrames() { 797 return collectedFrames; 798 } 799 800 // The takeWhile method arrange for stopping frame collection 801 // as soon as a frame from ReflectionFrames.class is reached. 802 // The first such frame encountered is still included in the 803 // collected frames, but collection stops right after. 804 // This makes it possible to filter out anything above the 805 // the test method frame, such as frames from the test 806 // framework. takeWhile(StackFrame f)807 public boolean takeWhile(StackFrame f) { 808 if (stop) return false; 809 if (verbose) System.out.println(" " + f); 810 stop = stop || f.getDeclaringClass() == ReflectionFrames.class; 811 return true; 812 } 813 814 // filter out implementation frames to avoid depending 815 // on implementation details. If present, Class::newInstance, 816 // Method::invoke and Constructor::newInstance will 817 // still appear in the collected frames, which is 818 // sufficient for the purpose of the test. 819 // In the case where the StackWalker itself is supposed to 820 // filter the reflection frames, then this filter will always 821 // return true. This way, if such a reflection frame appears when 822 // it sjould have been filtered by StackWalker, it will make the 823 // test fail. filter(StackFrame f)824 public boolean filter(StackFrame f) { 825 if (filterImplFrames && 826 f.getClassName().startsWith("jdk.internal.reflect.")) { 827 filtered++; 828 return false; 829 } 830 if (!verbose) System.out.println(" " + f); 831 return true; 832 } 833 frame(StackFrame f)834 public String frame(StackFrame f) { 835 return f.getClassName() + "::" + f.getMethodName(); 836 } 837 parse(Stream<StackFrame> s)838 List<String> parse(Stream<StackFrame> s) { 839 // Android-changed: libcore doesn't have Stream.takeWhile method yet. 840 // return s.takeWhile(this::takeWhile) 841 return s.filter(this::takeWhile) 842 .filter(this::filter) 843 .map(this::frame) 844 .collect(Collectors.toList()); 845 } 846 847 /** 848 * The Caller class is used to create instances of 849 * StackInspector, either direcltly, or throug reflection. 850 */ 851 public static class Caller { create(How how)852 public static StackInspector create(How how) throws Exception { 853 switch(how) { 854 case NEW: return new StackInspector(); 855 case CONSTRUCTOR: return StackInspector.class 856 .getConstructor().newInstance(); 857 case CLASS: return StackInspector.class.newInstance(); 858 default: throw new AssertionError(String.valueOf(how)); 859 } 860 } reflect(How how)861 public static StackInspector reflect(How how) throws Exception { 862 return (StackInspector) Caller.class.getMethod("create", How.class) 863 .invoke(null, how); 864 } handle(How how)865 public static StackInspector handle(How how) throws Exception { 866 Lookup lookup = MethodHandles.lookup(); 867 MethodHandle mh = lookup.findStatic(Caller.class, "create", 868 MethodType.methodType(StackInspector.class, How.class)); 869 try { 870 return (StackInspector) mh.invoke(how); 871 } catch (Error | Exception x) { 872 throw x; 873 } catch(Throwable t) { 874 throw new AssertionError(t); 875 } 876 } 877 } 878 getCaller()879 public static Class<?> getCaller() throws Exception { 880 return walker.get().getCallerClass(); 881 } 882 reflectCaller()883 public static Class<?> reflectCaller() throws Exception { 884 return (Class<?>)StackWalker.class.getMethod("getCallerClass") 885 .invoke(walker.get()); 886 } 887 supplyCaller()888 public static Class<?> supplyCaller() throws Exception { 889 return ((Supplier<Class<?>>)StackInspector.walker.get()::getCallerClass).get(); 890 } 891 handleCaller()892 public static Class<?> handleCaller() throws Exception { 893 Lookup lookup = MethodHandles.lookup(); 894 MethodHandle mh = lookup.findVirtual(StackWalker.class, "getCallerClass", 895 MethodType.methodType(Class.class)); 896 try { 897 return (Class<?>) mh.invoke(walker.get()); 898 } catch (Error | Exception x) { 899 throw x; 900 } catch(Throwable t) { 901 throw new AssertionError(t); 902 } 903 } 904 } 905 } 906