blob: 2d7fced04d24e988b9f91b6a787d023d8038e00d [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 {
}