Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  ReflectionFrames.java   Sprache: JAVA

 
/*
 * 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
 */


import java.lang.StackWalker.StackFrame;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.util.EnumSet;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.lang.StackWalker.Option.*;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;

public class ReflectionFrames {
    final static boolean verbose = false;
    final static Class<?> REFLECT_ACCESS = findClass("java.lang.reflect.ReflectAccess");
    final static Class<?> REFLECTION_FACTORY = findClass("jdk.internal.reflect.ReflectionFactory");

    private static Class<?> findClass(String cn) {
        try {
            return Class.forName(cn);
        } catch (ClassNotFoundException e) {
            throw new AssertionError(e);
        }
    }

    /**
     * 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
    public static void 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");

        StackInspector obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("create", How.class)
                             .invoke(null, How.NEW));
        assertEquals(obj.collectedFrames,
                     List.of(StackInspector.class.getName()
                                 +"::",
                             StackInspector.Caller.class.getName()
                                 +"::create",
                             ReflectionFrames.class.getName()
                                 +"::testNewStackInspector"));
        assertEquals(obj.cls, StackInspector.Caller.class);
        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 new StackInspector() directly.
        // No reflection frame should appear.
        System.out.println("testNewStackInspector: reflect");

        obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("reflect", How.class)
                             .invoke(null, How.NEW));
        assertEquals(obj.collectedFrames,
                     List.of(StackInspector.class.getName()
                                 +"::",
                             StackInspector.Caller.class.getName()
                                 +"::create",
                             StackInspector.Caller.class.getName()
                                 +"::reflect",
                             ReflectionFrames.class.getName()
                                 +"::testNewStackInspector"));
        assertEquals(obj.cls, StackInspector.Caller.class);
        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
        // a MethodHandle.
        // The create method invokes new StackInspector() directly.
        // No reflection frame should appear.
        System.out.println("testNewStackInspector: handle");

        obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("handle", How.class)
                             .invoke(null, How.NEW));
        assertEquals(obj.collectedFrames,
                     List.of(StackInspector.class.getName()
                                 +"::",
                             StackInspector.Caller.class.getName()
                                 +"::create",
                             StackInspector.Caller.class.getName()
                                 +"::handle",
                             ReflectionFrames.class.getName()
                                 +"::testNewStackInspector"));
        assertEquals(obj.cls, StackInspector.Caller.class);
        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 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");

        obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("create", How.class)
                             .invoke(null, How.NEW));
        assertEquals(obj.collectedFrames,
                     List.of(StackInspector.class.getName()
                                 +"::",
                             StackInspector.Caller.class.getName()
                                 +"::create",
                             Method.class.getName()
                                 +"::invoke",
                             ReflectionFrames.class.getName()
                                 +"::testNewStackInspector"));
        assertEquals(obj.cls, StackInspector.Caller.class);
        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 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");

        obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("reflect", How.class)
                             .invoke(null, How.NEW));
        assertEquals(obj.collectedFrames,
                     List.of(StackInspector.class.getName()
                                 +"::",
                             StackInspector.Caller.class.getName()
                                 +"::create",
                             Method.class.getName()
                                 +"::invoke",
                             StackInspector.Caller.class.getName()
                                 +"::reflect",
                             Method.class.getName()
                                 +"::invoke",
                             ReflectionFrames.class.getName()
                                 +"::testNewStackInspector"));
        assertEquals(obj.cls, StackInspector.Caller.class);
        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 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");

        obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("handle", How.class)
                             .invoke(null, How.NEW));
        assertEquals(obj.collectedFrames,
                     List.of(StackInspector.class.getName()
                                 +"::",
                             StackInspector.Caller.class.getName()
                                 +"::create",
                             // MethodHandle::invoke remains hidden
                             StackInspector.Caller.class.getName()
                                 +"::handle",
                             Method.class.getName()
                                 +"::invoke",
                             ReflectionFrames.class.getName()
                                 +"::testNewStackInspector"));
        assertEquals(obj.cls, StackInspector.Caller.class);
        assertNotEquals(obj.filtered, 0);
    }

   /**
     * 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
    public static void 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");

        StackInspector obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("create", How.class)
                             .invoke(null, How.CONSTRUCTOR));
        assertEquals(obj.collectedFrames,
                     List.of(StackInspector.class.getName()
                                 +"::",
                             StackInspector.Caller.class.getName()
                                 +"::create",
                             ReflectionFrames.class.getName()
                                 +"::testConstructor"));
        assertEquals(obj.cls, StackInspector.Caller.class);
        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 Constructor.newInstance().
        // No reflection frame should appear.
        System.out.println("testConstructor: reflect");

        obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("reflect", How.class)
                             .invoke(null, How.CONSTRUCTOR));
        assertEquals(obj.collectedFrames,
                     List.of(StackInspector.class.getName()
                                 +"::",
                             StackInspector.Caller.class.getName()
                                 +"::create",
                             StackInspector.Caller.class.getName()
                                 +"::reflect",
                             ReflectionFrames.class.getName()
                                 +"::testConstructor"));
        assertEquals(obj.cls, StackInspector.Caller.class);
        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
        // MethodHandle.
        // The create method invokes Constructor.newInstance().
        // No reflection frame should appear.
        System.out.println("testConstructor: handle");

        obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("handle", How.class)
                             .invoke(null, How.CONSTRUCTOR));
        assertEquals(obj.collectedFrames,
                     List.of(StackInspector.class.getName()
                                 +"::",
                             StackInspector.Caller.class.getName()
                                 +"::create",
                             StackInspector.Caller.class.getName()
                                 +"::handle",
                             ReflectionFrames.class.getName()
                                 +"::testConstructor"));
        assertEquals(obj.cls, StackInspector.Caller.class);
        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 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");

        obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("create", How.class)
                             .invoke(null, How.CONSTRUCTOR));
        assertEquals(obj.collectedFrames,
                     List.of(StackInspector.class.getName()
                                 +"::",
                             Constructor.class.getName()
                                 +"::newInstanceWithCaller",
                             Constructor.class.getName()
                                 +"::newInstance",
                             StackInspector.Caller.class.getName()
                                 +"::create",
                             Method.class.getName()
                                 +"::invoke",
                             ReflectionFrames.class.getName()
                                 +"::testConstructor"));
        assertEquals(obj.cls, StackInspector.Caller.class);
        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 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");

        obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("reflect", How.class)
                             .invoke(null, How.CONSTRUCTOR));
        assertEquals(obj.collectedFrames,
                     List.of(StackInspector.class.getName()
                                 +"::",
                             Constructor.class.getName()
                                 +"::newInstanceWithCaller",
                             Constructor.class.getName()
                                 +"::newInstance",
                             StackInspector.Caller.class.getName()
                                 +"::create",
                             Method.class.getName()
                                 +"::invoke",
                             StackInspector.Caller.class.getName()
                                 +"::reflect",
                             Method.class.getName()
                                 +"::invoke",
                             ReflectionFrames.class.getName()
                                 +"::testConstructor"));
        assertEquals(obj.cls, StackInspector.Caller.class);
        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 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");

        obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("handle", How.class)
                             .invoke(null, How.CONSTRUCTOR));
        assertEquals(obj.collectedFrames,
                     List.of(StackInspector.class.getName()
                                 +"::",
                             Constructor.class.getName()
                                 +"::newInstanceWithCaller",
                             Constructor.class.getName()
                                 +"::newInstance",
                             StackInspector.Caller.class.getName()
                                 +"::create",
                             // MethodHandle::invoke remains hidden
                             StackInspector.Caller.class.getName()
                                 +"::handle",
                             Method.class.getName()
                                 +"::invoke",
                             ReflectionFrames.class.getName()
                                 +"::testConstructor"));
        assertEquals(obj.cls, StackInspector.Caller.class);
        assertNotEquals(obj.filtered, 0);
    }

   /**
     * 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
    public static void 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");

        obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("reflect", 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",
                             StackInspector.Caller.class.getName()
                                 +"::reflect",
                             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.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");

        obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("handle", 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",
                             StackInspector.Caller.class.getName()
                                 +"::handle",
                             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);

        // 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");

        obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("reflect", How.class)
                             .invoke(null, How.CLASS));
        System.out.println(obj.collectedFrames);
        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",
                             StackInspector.Caller.class.getName()
                                 +"::reflect",
                             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.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");

        obj = ((StackInspector)StackInspector.Caller.class
                             .getMethod("handle", 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",
                             // MethodHandle::invoke remains hidden
                             StackInspector.Caller.class.getName()
                                 +"::handle",
                             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);
    }

    @Test
    public static void testGetCaller() throws Exception {
        // Sets the default walker which hides reflection
        // frames.
        StackInspector.walker.set(StackInspector.walkerHide);

        assertEquals(StackInspector.getCaller(), ReflectionFrames.class);
        assertEquals(StackInspector.class.getMethod("getCaller").invoke(null),
                     ReflectionFrames.class);

        // Sets a non-default walker configured to show
        // reflection frames
        StackInspector.walker.set(StackInspector.walkerShow);

        assertEquals(StackInspector.getCaller(), ReflectionFrames.class);
        assertEquals(StackInspector.class.getMethod("getCaller").invoke(null),
                     ReflectionFrames.class);
    }

    @Test
    public static void testReflectCaller() throws Exception {
        // Sets the default walker which hides reflection
        // frames.
        StackInspector.walker.set(StackInspector.walkerHide);

        assertEquals(StackInspector.reflectCaller(), ReflectionFrames.class);
        assertEquals(StackInspector.class.getMethod("reflectCaller").invoke(null),
                     ReflectionFrames.class);

        // Sets a non-default walker configured to show
        // reflection frames
        StackInspector.walker.set(StackInspector.walkerShow);

        assertEquals(StackInspector.reflectCaller(), ReflectionFrames.class);
        assertEquals(StackInspector.class.getMethod("reflectCaller").invoke(null),
                     ReflectionFrames.class);
    }

    @Test
    public static void testSupplyCaller() throws Exception {
        // Sets the default walker which hides reflection
        // frames.
        StackInspector.walker.set(StackInspector.walkerHide);

        assertEquals(StackInspector.supplyCaller(), ReflectionFrames.class);
        assertEquals(StackInspector.class.getMethod("supplyCaller").invoke(null),
                     ReflectionFrames.class);

        // Sets a non-default walker configured to show
        // reflection frames
        StackInspector.walker.set(StackInspector.walkerShow);

        assertEquals(StackInspector.supplyCaller(), ReflectionFrames.class);
        assertEquals(StackInspector.class.getMethod("supplyCaller").invoke(null),
                     ReflectionFrames.class);
    }

    @Test
    public static void testHandleCaller() throws Exception {
        // Sets the default walker which hides reflection
        // frames.
        StackInspector.walker.set(StackInspector.walkerHide);

        assertEquals(StackInspector.handleCaller(), ReflectionFrames.class);
        assertEquals(StackInspector.class.getMethod("handleCaller").invoke(null),
                     ReflectionFrames.class);

        // Sets a non-default walker configured to show
        // reflection frames
        StackInspector.walker.set(StackInspector.walkerShow);

        assertEquals(StackInspector.handleCaller(), ReflectionFrames.class);
        assertEquals(StackInspector.class.getMethod("handleCaller").invoke(null),
                     ReflectionFrames.class);
    }

    static enum How { NEW, CONSTRUCTOR, CLASS};

    /**
     * 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.
     */

    static class StackInspector {
        static final StackWalker walkerHide =
            StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
        static final StackWalker walkerShow =
            StackWalker.getInstance(EnumSet.of(
                           StackWalker.Option.RETAIN_CLASS_REFERENCE,
                           StackWalker.Option.SHOW_REFLECT_FRAMES));
        final static ThreadLocal<StackWalker> walker = new ThreadLocal<>() {
             protected StackWalker initialValue() {
                 return walkerHide;
             }
        };

        List<String> collectedFrames;
        Class<?> cls = null;
        boolean stop;
        int filtered;
        final boolean filterImplFrames;

        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.
        public boolean takeWhile(StackFrame f) {
            if (stop) return false;
            if (verbose) System.out.println(" " + f);
            stop = stop || f.getDeclaringClass() == ReflectionFrames.class;
            return true;
        }

        // 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.
        public boolean filter(StackFrame f) {
            if (filterImplFrames &&
                f.getClassName().startsWith("jdk.internal.reflect.")) {
                filtered++;
                return false;
            }
            if (!verbose) System.out.println(" " + f);
            return true;
        }

        public String frame(StackFrame f) {
            return f.getClassName() + "::" + f.getMethodName();
        }

        List<String> parse(Stream<StackFrame> s) {
            return s.takeWhile(this::takeWhile)
                    .filter(this::filter)
                    .map(this::frame)
                    .collect(Collectors.toList());
        }

        /**
         * The Caller class is used to create instances of
         * StackInspector, either direcltly, or throug reflection.
         */

        public static class Caller {
            public static StackInspector create(How how) throws Exception {
                switch(how) {
                    case NEWreturn new StackInspector();
                    case CONSTRUCTOR: return StackInspector.class
                        .getConstructor().newInstance();
                    case CLASSreturn StackInspector.class.newInstance();
                    defaultthrow new AssertionError(String.valueOf(how));
                }
            }
            public static StackInspector reflect(How how) throws Exception {
                return (StackInspector) Caller.class.getMethod("create", How.class)
                      .invoke(null, how);
            }
            public static StackInspector handle(How how) throws Exception {
                Lookup lookup = MethodHandles.lookup();
                MethodHandle mh = lookup.findStatic(Caller.class"create",
                        MethodType.methodType(StackInspector.class, How.class));
                try {
                    return (StackInspector) mh.invoke(how);
                } catch (Error | Exception x) {
                    throw x;
                } catch(Throwable t) {
                    throw new AssertionError(t);
                }
            }
        }

        public static Class<?> getCaller() throws Exception {
            return walker.get().getCallerClass();
        }

        public static Class<?> reflectCaller() throws Exception {
            return (Class<?>)StackWalker.class.getMethod("getCallerClass")
                .invoke(walker.get());
        }

        public static Class<?> supplyCaller() throws Exception {
            return ((Supplier<Class<?>>)StackInspector.walker.get()::getCallerClass).get();
        }

        public static Class<?> handleCaller() throws Exception {
            Lookup lookup = MethodHandles.lookup();
            MethodHandle mh = lookup.findVirtual(StackWalker.class"getCallerClass",
                    MethodType.methodType(Class.class));
            try {
                return (Class<?>) mh.invoke(walker.get());
            } catch (Error | Exception x) {
                throw x;
            } catch(Throwable t) {
                throw new AssertionError(t);
            }
        }
    }
}

94%


¤ Dauer der Verarbeitung: 0.27 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge