/src/java.base/share/classes/jdk/internal/reflect/CallerSensitiveAdapter.java
https://github.com/openjdk/valhalla · Java · 112 lines · 9 code · 4 blank · 99 comment · 0 complexity · 5dbfd0585503bcf1052fcdd868897897 MD5 · raw file
- /*
- * Copyright (c) 2021, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
- package jdk.internal.reflect;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- import static java.lang.annotation.ElementType.METHOD;
- /**
- * A method annotated @CallerSensitiveAdapter is an adapter method corresponding
- * to a caller-sensitive method, which is annotated with @CallerSensitive.
- *
- * A caller-sensitive adapter is private and has the same name as its
- * corresponding caller-sensitive method with a trailing caller class parameter.
- *
- * When a caller-sensitive method is invoked via Method::invoke or MethodHandle
- * the core reflection and method handle implementation will find if
- * an @CallerSensitiveAdapter method for that CSM is present. If present,
- * the runtime will invoke the adapter method with the caller class
- * argument instead. This special calling sequence ensures that the same caller
- * class is passed to a caller-sensitive method via Method::invoke,
- * MethodHandle::invokeExact, or a mix of these methods.
- *
- * For example, CSM::returnCallerClass is a caller-sensitive method
- * with an adapter method:
- * {@code
- * class CSM {
- * @CallerSensitive
- * static Class<?> returnCallerClass() {
- * return returnCallerClass(Reflection.getCallerClass());
- * }
- * @CallerSensitiveAdapter
- * private static Class<?> returnCallerClass(Class<?> caller) {
- * return caller;
- * }
- * }
- *
- * class Test {
- * void test() throws Throwable {
- * // calling CSM::returnCallerClass via reflection
- * var csm = CSM.class.getMethod("returnCallerClass");
- * // expect Foo to be the caller class
- * var caller = csm.invoke(null);
- * assert(caller == Test.class);
- * }
- * void test2() throws Throwable {
- * // method handle for Method::invoke
- * MethodHandle mh = MethodHandles.lookup().findVirtual(Method.class, "invoke",
- * methodType(Object.class, Object.class, Object[].class));
- * var csm = CSM.class.getMethod("returnCallerClass");
- * // invoke Method::invoke via method handle and the target method
- * // being invoked reflectively is CSM::returnCallerClass
- * var caller = mh.invoke(csm, null, null);
- * assert(caller == Test.class);
- * }
- * }
- * }
- *
- *
- * Both CSM::returnCallerClass and Method::invoke can have an adapter method
- * with a caller-class parameter defined. Test::test calls CSM::returnCallerClass
- * via Method::invoke which does the stack walking to find the caller's class.
- * It will pass the caller's class directly to the adapter method for
- * CSM::returnCallerClass.
- *
- * Similarly, Test::test2 invokes the method handle of Method::invoke to
- * call CSM::returnCallerClass reflectively. In that case, MethodHandle::invokeExact
- * uses the lookup class of the Lookup object producing the method handle
- * as the caller's class, so no stack walking involved. The lookup class is Test.
- * It will invoke the adapter method of Method::invoke with Test as the caller's
- * class, which in turn invokes the adapter method of CSM::returnCallerClass
- * with Test as the caller. The calling sequence eliminates the need for
- * multiple stack walks when a caller-sensitive method is invoked reflectively.
- *
- * For caller-sensitive methods that require an exact caller class, the adapter
- * method must be defined for correctness. {@link java.lang.invoke.MethodHandles#lookup()}
- * and {@link ClassLoader#registerAsParallelCapable()} are the only two methods
- * in the JDK that need the exact caller class.
- *
- * On the other hand, for caller-sensitive methods that use the caller's class
- * for access checks or security permission checks, i.e., based on its runtime
- * package, defining loader, or protection domain, the adapter method is optional.
- */
- @Retention(RetentionPolicy.CLASS)
- @Target({METHOD})
- public @interface CallerSensitiveAdapter {
- }