83
84 package jdk.dynalink.beans;
85
86 import java.lang.invoke.MethodHandle;
87 import java.lang.invoke.MethodHandles;
88 import java.lang.invoke.MethodType;
89 import java.lang.reflect.AccessibleObject;
90 import java.lang.reflect.Constructor;
91 import java.lang.reflect.Executable;
92 import java.lang.reflect.Member;
93 import java.lang.reflect.Method;
94 import java.lang.reflect.Modifier;
95 import java.lang.reflect.Module;
96 import java.security.AccessControlContext;
97 import java.security.AccessController;
98 import java.security.PrivilegedAction;
99 import jdk.dynalink.CallSiteDescriptor;
100 import jdk.dynalink.SecureLookupSupplier;
101 import jdk.dynalink.internal.AccessControlContextFactory;
102 import jdk.dynalink.linker.support.Lookup;
103 import jdk.internal.module.Modules;
104 import jdk.internal.reflect.CallerSensitive;
105
106
107 /**
108 * A dynamic method bound to exactly one Java method or constructor that is caller sensitive. Since the target method is
109 * caller sensitive, it doesn't cache a method handle but rather uses the passed lookup object in
110 * {@link #getTarget(CallSiteDescriptor)} to unreflect a method handle from the reflective member on
111 * every request.
112 */
113 class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
114 private static final AccessControlContext GET_LOOKUP_CONTEXT =
115 AccessControlContextFactory.createAccessControlContext(
116 SecureLookupSupplier.GET_LOOKUP_PERMISSION_NAME);
117
118 // Typed as "AccessibleObject" as it can be either a method or a constructor.
119 // If we were Java8-only, we could use java.lang.reflect.Executable
120 private final AccessibleObject target;
121 private final MethodType type;
122
123 CallerSensitiveDynamicMethod(final AccessibleObject target) {
163 (PrivilegedAction<MethodHandles.Lookup>)()->desc.getLookup(),
164 GET_LOOKUP_CONTEXT);
165
166 if(target instanceof Method) {
167 final MethodHandle mh = unreflect(lookup, (Method)target);
168 if(Modifier.isStatic(((Member)target).getModifiers())) {
169 return StaticClassIntrospector.editStaticMethodHandle(mh);
170 }
171 return mh;
172 }
173 return StaticClassIntrospector.editConstructorMethodHandle(unreflectConstructor(lookup,
174 (Constructor<?>)target));
175 }
176
177 @Override
178 boolean isConstructor() {
179 return target instanceof Constructor;
180 }
181
182 private static MethodHandle unreflect(final MethodHandles.Lookup lookup, final Method m) {
183 try {
184 return Lookup.unreflect(lookup, m);
185 } catch (final IllegalAccessError iae) {
186 if (addModuleRead(lookup, m)) {
187 try {
188 return Lookup.unreflect(lookup, m);
189 } catch (final IllegalAccessError e2) {
190 // fall through and throw original error as cause
191 }
192 }
193 throw iae;
194 }
195 }
196
197 private static MethodHandle unreflectConstructor(final MethodHandles.Lookup lookup, final Constructor<?> c) {
198 try {
199 return Lookup.unreflectConstructor(lookup, c);
200 } catch (final IllegalAccessError iae) {
201 if (addModuleRead(lookup, c)) {
202 try {
203 return Lookup.unreflectConstructor(lookup, c);
204 } catch (final IllegalAccessError e2) {
205 // fall through and throw original error as cause
206 }
207 }
208 throw iae;
209 }
210 }
211
212
213 private static boolean addModuleRead(final MethodHandles.Lookup lookup, final Executable e) {
214 // Don't add module read link if this is not a CallerSensitive member
215 if (!e.isAnnotationPresent(CallerSensitive.class)) {
216 return false;
217 }
218
219 // If the lookup is public lookup, don't bother adding module read link!
220 // public lookup cannot unreflect caller sensitives anyway!
221 if (lookup == MethodHandles.publicLookup()) {
222 return false;
223 }
224
225 // try to add missing module read from using module to declararing module!
226 final Class<?> declClass = e.getDeclaringClass();
227 final Module useModule = lookup.lookupClass().getModule();
228 final Module declModule = declClass.getModule();
229 if (useModule != null && declModule != null && declModule.isExported(declClass.getPackageName())) {
230 Modules.addReads(useModule, declModule);
231 return true;
232 }
233
234 return false;
235 }
236 }
|
83
84 package jdk.dynalink.beans;
85
86 import java.lang.invoke.MethodHandle;
87 import java.lang.invoke.MethodHandles;
88 import java.lang.invoke.MethodType;
89 import java.lang.reflect.AccessibleObject;
90 import java.lang.reflect.Constructor;
91 import java.lang.reflect.Executable;
92 import java.lang.reflect.Member;
93 import java.lang.reflect.Method;
94 import java.lang.reflect.Modifier;
95 import java.lang.reflect.Module;
96 import java.security.AccessControlContext;
97 import java.security.AccessController;
98 import java.security.PrivilegedAction;
99 import jdk.dynalink.CallSiteDescriptor;
100 import jdk.dynalink.SecureLookupSupplier;
101 import jdk.dynalink.internal.AccessControlContextFactory;
102 import jdk.dynalink.linker.support.Lookup;
103 import jdk.internal.reflect.CallerSensitive;
104
105
106 /**
107 * A dynamic method bound to exactly one Java method or constructor that is caller sensitive. Since the target method is
108 * caller sensitive, it doesn't cache a method handle but rather uses the passed lookup object in
109 * {@link #getTarget(CallSiteDescriptor)} to unreflect a method handle from the reflective member on
110 * every request.
111 */
112 class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
113 private static final AccessControlContext GET_LOOKUP_CONTEXT =
114 AccessControlContextFactory.createAccessControlContext(
115 SecureLookupSupplier.GET_LOOKUP_PERMISSION_NAME);
116
117 // Typed as "AccessibleObject" as it can be either a method or a constructor.
118 // If we were Java8-only, we could use java.lang.reflect.Executable
119 private final AccessibleObject target;
120 private final MethodType type;
121
122 CallerSensitiveDynamicMethod(final AccessibleObject target) {
162 (PrivilegedAction<MethodHandles.Lookup>)()->desc.getLookup(),
163 GET_LOOKUP_CONTEXT);
164
165 if(target instanceof Method) {
166 final MethodHandle mh = unreflect(lookup, (Method)target);
167 if(Modifier.isStatic(((Member)target).getModifiers())) {
168 return StaticClassIntrospector.editStaticMethodHandle(mh);
169 }
170 return mh;
171 }
172 return StaticClassIntrospector.editConstructorMethodHandle(unreflectConstructor(lookup,
173 (Constructor<?>)target));
174 }
175
176 @Override
177 boolean isConstructor() {
178 return target instanceof Constructor;
179 }
180
181 private static MethodHandle unreflect(final MethodHandles.Lookup lookup, final Method m) {
182 return Lookup.unreflect(lookup, m);
183 }
184
185 private static MethodHandle unreflectConstructor(final MethodHandles.Lookup lookup, final Constructor<?> c) {
186 return Lookup.unreflectConstructor(lookup, c);
187 }
188 }
|