提交 6a4b3466 编写于 作者: J jrose

8025112: JSR 292 spec updates for security manager and caller sensitivity

Summary: align CONSTANT_MethodHandle and Lookup.find* API calls, clarify security manager & @CallerSensitive interactions
Reviewed-by: mchung, twisti
上级 31532c96
...@@ -1330,6 +1330,11 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); ...@@ -1330,6 +1330,11 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
return null; // DMH returns DMH.member return null; // DMH returns DMH.member
} }
/*non-public*/
Class<?> internalCallerClass() {
return null; // caller-bound MH for @CallerSensitive method returns caller
}
/*non-public*/ /*non-public*/
MethodHandle withInternalMemberName(MemberName member) { MethodHandle withInternalMemberName(MemberName member) {
if (member != null) { if (member != null) {
......
...@@ -381,6 +381,10 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -381,6 +381,10 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
MemberName internalMemberName() { MemberName internalMemberName() {
return asFixedArity().internalMemberName(); return asFixedArity().internalMemberName();
} }
@Override
Class<?> internalCallerClass() {
return asFixedArity().internalCallerClass();
}
/*non-public*/ /*non-public*/
@Override @Override
...@@ -831,7 +835,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -831,7 +835,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
MethodHandle vamh = prepareForInvoker(mh); MethodHandle vamh = prepareForInvoker(mh);
// Cache the result of makeInjectedInvoker once per argument class. // Cache the result of makeInjectedInvoker once per argument class.
MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass); MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
return restoreToType(bccInvoker.bindTo(vamh), mh.type(), mh.internalMemberName()); return restoreToType(bccInvoker.bindTo(vamh), mh.type(), mh.internalMemberName(), hostClass);
} }
private static MethodHandle makeInjectedInvoker(Class<?> hostClass) { private static MethodHandle makeInjectedInvoker(Class<?> hostClass) {
...@@ -886,10 +890,12 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -886,10 +890,12 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
} }
// Undo the adapter effect of prepareForInvoker: // Undo the adapter effect of prepareForInvoker:
private static MethodHandle restoreToType(MethodHandle vamh, MethodType type, MemberName member) { private static MethodHandle restoreToType(MethodHandle vamh, MethodType type,
MemberName member,
Class<?> hostClass) {
MethodHandle mh = vamh.asCollector(Object[].class, type.parameterCount()); MethodHandle mh = vamh.asCollector(Object[].class, type.parameterCount());
mh = mh.asType(type); mh = mh.asType(type);
mh = mh.withInternalMemberName(member); mh = new WrappedMember(mh, type, member, hostClass);
return mh; return mh;
} }
...@@ -958,11 +964,13 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -958,11 +964,13 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
static class WrappedMember extends MethodHandle { static class WrappedMember extends MethodHandle {
private final MethodHandle target; private final MethodHandle target;
private final MemberName member; private final MemberName member;
private final Class<?> callerClass;
private WrappedMember(MethodHandle target, MethodType type, MemberName member) { private WrappedMember(MethodHandle target, MethodType type, MemberName member, Class<?> callerClass) {
super(type, reinvokerForm(target)); super(type, reinvokerForm(target));
this.target = target; this.target = target;
this.member = member; this.member = member;
this.callerClass = callerClass;
} }
@Override @Override
...@@ -980,19 +988,23 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -980,19 +988,23 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
return member; return member;
} }
@Override @Override
Class<?> internalCallerClass() {
return callerClass;
}
@Override
boolean isInvokeSpecial() { boolean isInvokeSpecial() {
return target.isInvokeSpecial(); return target.isInvokeSpecial();
} }
@Override @Override
MethodHandle viewAsType(MethodType newType) { MethodHandle viewAsType(MethodType newType) {
return new WrappedMember(target, newType, member); return new WrappedMember(target, newType, member, callerClass);
} }
} }
static MethodHandle makeWrappedMember(MethodHandle target, MemberName member) { static MethodHandle makeWrappedMember(MethodHandle target, MemberName member) {
if (member.equals(target.internalMemberName())) if (member.equals(target.internalMemberName()))
return target; return target;
return new WrappedMember(target, target.type(), member); return new WrappedMember(target, target.type(), member, null);
} }
} }
...@@ -61,6 +61,18 @@ import static java.lang.invoke.MethodHandleStatics.*; ...@@ -61,6 +61,18 @@ import static java.lang.invoke.MethodHandleStatics.*;
* Cracking must be done via a {@code Lookup} object equivalent to that which created * Cracking must be done via a {@code Lookup} object equivalent to that which created
* the target method handle, or which has enough access permissions to recreate * the target method handle, or which has enough access permissions to recreate
* an equivalent method handle. * an equivalent method handle.
* <p>
* If the underlying method is <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a>,
* the direct method handle will have been "bound" to a particular caller class, the
* {@linkplain java.lang.invoke.MethodHandles.Lookup#lookupClass() lookup class}
* of the lookup object used to create it.
* Cracking this method handle with a different lookup class will fail
* even if the underlying method is public (like {@code Class.forName}).
* <p>
* The requirement of lookup object matching provides a "fast fail" behavior
* for programs which may otherwise trust erroneous revelation of a method
* handle with symbolic information (or caller binding) from an unexpected scope.
* Use {@link java.lang.invoke.MethodHandles#reflectAs} to override this limitation.
* *
* <h1><a name="refkinds"></a>Reference kinds</h1> * <h1><a name="refkinds"></a>Reference kinds</h1>
* The <a href="MethodHandles.Lookup.html#lookups">Lookup Factory Methods</a> * The <a href="MethodHandles.Lookup.html#lookups">Lookup Factory Methods</a>
......
...@@ -107,6 +107,11 @@ public class MethodHandleProxies { ...@@ -107,6 +107,11 @@ public class MethodHandleProxies {
* such as abstract classes with single abstract methods. * such as abstract classes with single abstract methods.
* Future versions of this API may also equip wrapper instances * Future versions of this API may also equip wrapper instances
* with one or more additional public "marker" interfaces. * with one or more additional public "marker" interfaces.
* <p>
* If a security manager is installed, this method is caller sensitive.
* During any invocation of the target method handle via the returned wrapper,
* the original creator of the wrapper (the caller) will be visible
* to context checks requested by the security manager.
* *
* @param <T> the desired type of the wrapper, a single-method interface * @param <T> the desired type of the wrapper, a single-method interface
* @param intfc a class object representing {@code T} * @param intfc a class object representing {@code T}
......
...@@ -47,7 +47,10 @@ public class TestPrivateMember { ...@@ -47,7 +47,10 @@ public class TestPrivateMember {
MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType mt = MethodType.methodType(void.class); MethodType mt = MethodType.methodType(void.class);
try { try {
MethodHandle mh = lookup.findStatic(Class.class, "checkInitted", mt); Class<?> checkInittedHolder = TestPrivateMemberPackageSibling.class;
// Original model: checkInittedHolder = Class.class;
// Not using Class.checkInitted because it could change without notice.
MethodHandle mh = lookup.findStatic(checkInittedHolder, "checkInitted", mt);
throw new RuntimeException("IllegalAccessException not thrown"); throw new RuntimeException("IllegalAccessException not thrown");
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
// okay // okay
...@@ -55,3 +58,7 @@ public class TestPrivateMember { ...@@ -55,3 +58,7 @@ public class TestPrivateMember {
} }
} }
} }
class TestPrivateMemberPackageSibling {
private static void checkInitted() { }
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册