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