/* * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/* * @test * @bug 8173898 * @summary Basic test for checking filtering of reflection frames * @run testng ReflectionFrames
*/
/** * This test invokes new StackInspector() directly from * the caller StackInspector.Caller.create method. * It checks that the caller is StackInspector.Caller. * It also checks the expected frames collected * by walking the stack from the default StackInspector() * constructor. * This is done twice, once using a default StackWalker * that hides reflection frames, once using a StackWalker * configured to show reflection frames.
*/
@Test publicstaticvoid testNewStackInspector() throws Exception { // Sets the default walker which hides reflection // frames.
StackInspector.walker.set(StackInspector.walkerHide);
// Calls the StackInspector.create method through reflection // and check the frames collected in the StackInspector // default constructor. // The create method invokes new StackInspector() directly. // No reflection frame should appear.
System.out.println("testNewStackInspector: create");
// Calls the StackInspector.reflect method through reflection // and check the frames collected in the StackInspector // default constructor. // The reflect method invokes the create method through // reflection. // The create method invokes new StackInspector() directly. // No reflection frame should appear.
System.out.println("testNewStackInspector: reflect");
// Calls the StackInspector.handle method through reflection // and check the frames collected in the StackInspector // default constructor. // The handle method invokes the create method using // a MethodHandle. // The create method invokes new StackInspector() directly. // No reflection frame should appear.
System.out.println("testNewStackInspector: handle");
// Sets a non-default walker configured to show // reflection frames
StackInspector.walker.set(StackInspector.walkerShow);
// Calls the StackInspector.create method through reflection // and check the frames collected in the StackInspector // default constructor. // The create method invokes new StackInspector() directly. // We should see all reflection frames, except the // jdk.internal.reflect frames which we are filtering // out in StackInspector::filter.
System.out.println("testNewStackInspector: create: show reflect");
// Calls the StackInspector.reflect method through reflection // and check the frames collected in the StackInspector // default constructor. // The reflect method invokes the create method through // reflection. // The create method invokes new StackInspector() directly. // We should see all reflection frames, except the // jdk.internal.reflect frames which we are filtering // out in StackInspector::filter.
System.out.println("testNewStackInspector: reflect: show reflect");
// Calls the StackInspector.handle method through reflection // and check the frames collected in the StackInspector // default constructor. // The handle method invokes the create method using // MethodHandle. // The create method invokes new StackInspector() directly. // We should see all reflection frames, except the // jdk.internal.reflect frames which we are filtering // out in StackInspector::filter.
System.out.println("testNewStackInspector: handle: show reflect");
/** * This test invokes Constructor.newInstance() from * the caller StackInspector.Caller.create method. * It checks that the caller is StackInspector.Caller. * It also checks the expected frames collected * by walking the stack from the default StackInspector() * constructor. * This is done twice, once using a default StackWalker * that hides reflection frames, once using a StackWalker * configured to show reflection frames.
*/
@Test publicstaticvoid testConstructor() throws Exception { // Sets the default walker which hides reflection // frames.
StackInspector.walker.set(StackInspector.walkerHide);
// Calls the StackInspector.create method through reflection // and check the frames collected in the StackInspector // default constructor. // The create method invokes Constructor.newInstance(). // No reflection frame should appear.
System.out.println("testConstructor: create");
// Calls the StackInspector.reflect method through reflection // and check the frames collected in the StackInspector // default constructor. // The reflect method invokes the create method through // reflection. // The create method invokes Constructor.newInstance(). // No reflection frame should appear.
System.out.println("testConstructor: reflect");
// Calls the StackInspector.handle method through reflection // and check the frames collected in the StackInspector // default constructor. // The handle method invokes the create method using // MethodHandle. // The create method invokes Constructor.newInstance(). // No reflection frame should appear.
System.out.println("testConstructor: handle");
// Sets a non-default walker configured to show // reflection frames
StackInspector.walker.set(StackInspector.walkerShow);
// Calls the StackInspector.create method through reflection // and check the frames collected in the StackInspector // default constructor. // The create method invokes Constructor.newInstance(). // We should see all reflection frames, except the // jdk.internal.reflect frames which we are filtering // out in StackInspector::filter.
System.out.println("testConstructor: create: show reflect");
// Calls the StackInspector.reflect method through reflection // and check the frames collected in the StackInspector // default constructor. // The reflect method invokes the create method through // reflection. // The create method invokes Constructor.newInstance(). // We should see all reflection frames, except the // jdk.internal.reflect frames which we are filtering // out in StackInspector::filter.
System.out.println("testConstructor: reflect: show reflect");
// Calls the StackInspector.handle method through reflection // and check the frames collected in the StackInspector // default constructor. // The handle method invokes the create method using // MethodHandle. // The create method invokes Constructor.newInstance(). // We should see all reflection frames, except the // jdk.internal.reflect frames which we are filtering // out in StackInspector::filter.
System.out.println("testConstructor: handle: show reflect");
/** * This test invokes StackInspector.class.newInstance() from * the caller StackInspector.Caller.create method. Because * Class.newInstance() is not considered as a * reflection frame, the caller returned by * getCallerClass() should appear to be java.lang.Class * and not StackInspector.Caller. * It also checks the expected frames collected * by walking the stack from the default StackInspector() * constructor. * This is done twice, once using a default StackWalker * that hides reflection frames, once using a StackWalker * configured to show reflection frames.
*/
@Test publicstaticvoid testNewInstance() throws Exception { // Sets the default walker which hides reflection // frames.
StackInspector.walker.set(StackInspector.walkerHide);
// Calls the StackInspector.create method through reflection // and check the frames collected in the StackInspector // default constructor. // The create method invokes StackInspector.class.newInstance(). // No reflection frame should appear, except // Class::newInstance which is not considered as // a reflection frame.
System.out.println("testNewInstance: create");
StackInspector obj = ((StackInspector)StackInspector.Caller.class
.getMethod("create", How.class)
.invoke(null, How.CLASS));
assertEquals(obj.collectedFrames,
List.of(StackInspector.class.getName()
+"::",
REFLECT_ACCESS.getName()
+"::newInstance",
REFLECTION_FACTORY.getName()
+"::newInstance", Class.class.getName()
+"::newInstance",
StackInspector.Caller.class.getName()
+"::create",
ReflectionFrames.class.getName()
+"::testNewInstance")); // Because implementation frames are not filtered, then the // caller is ReflectAccess.class
assertEquals(obj.cls, REFLECT_ACCESS);
assertEquals(obj.filtered, 0);
// Calls the StackInspector.reflect method through reflection // and check the frames collected in the StackInspector // default constructor. // The reflect method invokes the create method through // reflection. // The create method invokes StackInspector.class.newInstance(). // No reflection frame should appear, except // Class::newInstance which is not considered as // a reflection frame.
System.out.println("testNewInstance: reflect");
// Because implementation frames are not filtered, then the // caller is ReflectAccess.class
assertEquals(obj.cls, REFLECT_ACCESS);
assertEquals(obj.filtered, 0);
// Calls the StackInspector.handle method through reflection // and check the frames collected in the StackInspector // default constructor. // The handle method invokes the create method using // reflection. // The create method invokes StackInspector.class.newInstance(). // No reflection frame should appear, except // Class::newInstance which is not considered as // a reflection frame.
System.out.println("testNewInstance: handle");
// Because implementation frames are not filtered, then the // caller is ReflectAccess.class
assertEquals(obj.cls, REFLECT_ACCESS);
assertEquals(obj.filtered, 0);
// Sets a non-default walker configured to show // reflection frames
StackInspector.walker.set(StackInspector.walkerShow);
// Calls the StackInspector.create method through reflection // and check the frames collected in the StackInspector // default constructor. // The create method invokes StackInspector.class.newInstance(). // We should see all reflection frames, except the // jdk.internal.reflect frames which we are filtering // out in StackInspector::filter.
System.out.println("testNewInstance: create: show reflect");
obj = ((StackInspector)StackInspector.Caller.class
.getMethod("create", How.class)
.invoke(null, How.CLASS));
assertEquals(obj.collectedFrames,
List.of(StackInspector.class.getName()
+"::",
Constructor.class.getName()
+"::newInstanceWithCaller",
REFLECT_ACCESS.getName()
+"::newInstance", Class.class.getName()
+"::newInstance",
StackInspector.Caller.class.getName()
+"::create",
Method.class.getName()
+"::invoke",
ReflectionFrames.class.getName()
+"::testNewInstance")); // Because implementation frames are not filtered, then the // caller is ReflectAccess.class
assertEquals(obj.cls, REFLECT_ACCESS);
assertNotEquals(obj.filtered, 0);
// Calls the StackInspector.reflect method through reflection // and check the frames collected in the StackInspector // default constructor. // The reflect method invokes the create method through // reflection. // The create method invokes StackInspector.class.newInstance(). // We should see all reflection frames, except the // jdk.internal.reflect frames which we are filtering // out in StackInspector::filter.
System.out.println("testNewInstance: reflect: show reflect");
// Because implementation frames are not filtered, then the // caller is ReflectAccess.class
assertEquals(obj.cls, REFLECT_ACCESS);
assertNotEquals(obj.filtered, 0);
// Calls the StackInspector.handle method through reflection // and check the frames collected in the StackInspector // default constructor. // The handle method invokes the create method using // MethodHandle. // The create method invokes StackInspector.class.newInstance(). // We should see all reflection frames, except the // jdk.internal.reflect frames which we are filtering // out in StackInspector::filter.
System.out.println("testNewInstance: handle: show reflect");
// Because implementation frames are not filtered, then the // caller is ReflectAccess.class
assertEquals(obj.cls, REFLECT_ACCESS);
assertNotEquals(obj.filtered, 0);
}
@Test publicstaticvoid testGetCaller() throws Exception { // Sets the default walker which hides reflection // frames.
StackInspector.walker.set(StackInspector.walkerHide);
/** * An object that collect stack frames by walking the stack * (and calling getCallerClass()) from within its constructor. * For the purpose of this test, StackInspector objects are * always created from the nested StackInspector.Caller class, * which should therefore appear as the caller of the * StackInspector constructor.
*/ staticclass StackInspector { staticfinal StackWalker walkerHide =
StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); staticfinal StackWalker walkerShow =
StackWalker.getInstance(EnumSet.of(
StackWalker.Option.RETAIN_CLASS_REFERENCE,
StackWalker.Option.SHOW_REFLECT_FRAMES)); finalstatic ThreadLocal<StackWalker> walker = new ThreadLocal<>() { protected StackWalker initialValue() { return walkerHide;
}
};
public StackInspector() {
stop = false; // if reflection frames are not hidden, we want to // filter implementation frames before collecting // to avoid depending on internal details.
filterImplFrames = walker.get() == walkerShow;
collectedFrames = walker.get().walk(this::parse);
cls = walker.get().getCallerClass();
}
public List<String> collectedFrames() { return collectedFrames;
}
// The takeWhile method arrange for stopping frame collection // as soon as a frame from ReflectionFrames.class is reached. // The first such frame encountered is still included in the // collected frames, but collection stops right after. // This makes it possible to filter out anything above the // the test method frame, such as frames from the test // framework. publicboolean takeWhile(StackFrame f) { if (stop) returnfalse; if (verbose) System.out.println(" " + f);
stop = stop || f.getDeclaringClass() == ReflectionFrames.class; returntrue;
}
// filter out implementation frames to avoid depending // on implementation details. If present, Class::newInstance, // Method::invoke and Constructor::newInstance will // still appear in the collected frames, which is // sufficient for the purpose of the test. // In the case where the StackWalker itself is supposed to // filter the reflection frames, then this filter will always // return true. This way, if such a reflection frame appears when // it sjould have been filtered by StackWalker, it will make the // test fail. publicboolean filter(StackFrame f) { if (filterImplFrames &&
f.getClassName().startsWith("jdk.internal.reflect.")) {
filtered++; returnfalse;
} if (!verbose) System.out.println(" " + f); returntrue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.