53
53
import java .util .Objects ;
54
54
import java .util .Set ;
55
55
56
+ import com .oracle .svm .util .ReflectionUtil ;
57
+ import jdk .graal .compiler .graph .Node ;
58
+ import jdk .graal .compiler .nodes .java .DynamicNewInstanceNode ;
59
+ import jdk .graal .compiler .nodes .java .DynamicNewInstanceWithExceptionNode ;
56
60
import org .graalvm .collections .EconomicMap ;
57
61
import org .graalvm .collections .EconomicSet ;
58
62
@@ -183,6 +187,13 @@ public record MethodInfo(DynamicAccessKind accessKind, String signature) {
183
187
new MethodSignature ("resolveConstantDesc" , MethodHandles .Lookup .class )));
184
188
reflectionMethodSignatures .put (MethodHandleProxies .class , Set .of (
185
189
new MethodSignature ("asInterfaceInstance" , Class .class , MethodHandle .class )));
190
+ reflectionMethodSignatures .put (jdk .internal .misc .Unsafe .class , Set .of (
191
+ new MethodSignature ("allocateInstance" , Class .class )));
192
+ if (ModuleLayer .boot ().findModule ("jdk.unsupported" ).isPresent ()) {
193
+ Class <?> sunMiscUnsafeClass = ReflectionUtil .lookupClass ("sun.misc.Unsafe" );
194
+ reflectionMethodSignatures .put (sunMiscUnsafeClass , Set .of (
195
+ new MethodSignature ("allocateInstance" , Class .class )));
196
+ }
186
197
187
198
reflectionMethodSignatures .put (ObjectOutputStream .class , Set .of (
188
199
new MethodSignature ("writeObject" , Object .class ),
@@ -210,6 +221,7 @@ public record MethodInfo(DynamicAccessKind accessKind, String signature) {
210
221
new MethodSignature ("getResourceAsStream" , String .class )));
211
222
resourceMethodSignatures .put (Class .class , Set .of (
212
223
new MethodSignature ("getResource" , String .class ),
224
+
213
225
new MethodSignature ("getResourceAsStream" , String .class )));
214
226
215
227
foreignMethodSignatures .put (Linker .class , Set .of (
@@ -224,18 +236,45 @@ public DynamicAccessDetectionPhase() {
224
236
225
237
@ Override
226
238
protected void run (StructuredGraph graph , CoreProviders context ) {
227
- List <MethodCallTargetNode > callTargetNodes = graph .getNodes (MethodCallTargetNode .TYPE ).snapshot ();
228
- for (MethodCallTargetNode callTarget : callTargetNodes ) {
229
- AnalysisType callerClass = (AnalysisType ) graph .method ().getDeclaringClass ();
230
- String sourceEntry = getSourceEntry (callerClass );
231
- MethodInfo methodInfo = getMethodInfo (callTarget .targetMethod ());
232
-
233
- if (methodInfo != null && sourceEntry != null ) {
234
- NodeSourcePosition nspToShow = callTarget .getNodeSourcePosition ();
235
- if (nspToShow != null && !dynamicAccessDetectionFeature .containsFoldEntry (nspToShow .getBCI (), nspToShow .getMethod ())) {
236
- String callLocation = nspToShow .getMethod ().asStackTraceElement (nspToShow .getBCI ()).toString ();
237
- dynamicAccessDetectionFeature .addCall (sourceEntry , methodInfo .accessKind (), methodInfo .signature (), callLocation );
238
- }
239
+ AnalysisType callerClass = (AnalysisType ) graph .method ().getDeclaringClass ();
240
+ String sourceEntry = getSourceEntry (callerClass );
241
+ if (sourceEntry == null ) {
242
+ return ;
243
+ }
244
+
245
+ for (Node node : graph .getNodes ()) {
246
+ ResolvedJavaMethod targetMethod = null ;
247
+ NodeSourcePosition invokeLocation = null ;
248
+ if (node instanceof MethodCallTargetNode callTarget ) {
249
+ targetMethod = callTarget .targetMethod ();
250
+ invokeLocation = callTarget .getNodeSourcePosition ();
251
+ } else if (node instanceof DynamicNewInstanceNode unsafeNode && unsafeNode .getNodeSourcePosition () != null && unsafeNode .isOriginUnsafeAllocateInstance ()) {
252
+ /*
253
+ * Match only DynamicNewInstanceNode intrinsified from Unsafe#allocateInstance. The
254
+ * NodeSourcePosition of the node preserves both the intrinsified method
255
+ * (getMethod()) and its original caller (getCaller()).
256
+ */
257
+ targetMethod = unsafeNode .getNodeSourcePosition ().getMethod ();
258
+ invokeLocation = unsafeNode .getNodeSourcePosition ().getCaller ();
259
+ } else if (node instanceof DynamicNewInstanceWithExceptionNode unsafeNodeEx && unsafeNodeEx .getNodeSourcePosition () != null && unsafeNodeEx .isOriginUnsafeAllocateInstance ()) {
260
+ /*
261
+ * Match only DynamicNewInstanceWithExceptionNode intrinsified from
262
+ * Unsafe#allocateInstance. The NodeSourcePosition of the node preserves both the
263
+ * intrinsified method (getMethod()) and its original caller (getCaller()).
264
+ */
265
+ targetMethod = unsafeNodeEx .getNodeSourcePosition ().getMethod ();
266
+ invokeLocation = unsafeNodeEx .getNodeSourcePosition ().getCaller ();
267
+ }
268
+ registerDynamicAccessCall (invokeLocation , targetMethod , sourceEntry );
269
+ }
270
+ }
271
+
272
+ private void registerDynamicAccessCall (NodeSourcePosition invokeLocation , ResolvedJavaMethod targetMethod , String sourceEntry ) {
273
+ if (invokeLocation != null && !dynamicAccessDetectionFeature .containsFoldEntry (invokeLocation .getBCI (), invokeLocation .getMethod ())) {
274
+ MethodInfo dynamicAccessMethodInfo = lookupDynamicAccessMethod (targetMethod );
275
+ if (dynamicAccessMethodInfo != null ) {
276
+ String callLocation = invokeLocation .getMethod ().asStackTraceElement (invokeLocation .getBCI ()).toString ();
277
+ dynamicAccessDetectionFeature .addCall (sourceEntry , dynamicAccessMethodInfo .accessKind (), dynamicAccessMethodInfo .signature (), callLocation );
239
278
}
240
279
}
241
280
}
@@ -245,33 +284,31 @@ protected void run(StructuredGraph graph, CoreProviders context) {
245
284
* method if it exists in the predetermined set, based on its graph and MethodCallTargetNode;
246
285
* otherwise, returns null.
247
286
*/
248
- private static MethodInfo getMethodInfo (ResolvedJavaMethod method ) {
287
+ private static MethodInfo lookupDynamicAccessMethod (ResolvedJavaMethod method ) {
249
288
Class <?> declaringClass = OriginalClassProvider .getJavaClass (method .getDeclaringClass ());
250
- if (!reflectionMethodSignatures .containsKey (declaringClass ) &&
251
- !resourceMethodSignatures .containsKey (declaringClass ) &&
252
- !foreignMethodSignatures .containsKey (declaringClass )) {
253
- return null ;
289
+
290
+ Set <MethodSignature > reflectionSignatures = reflectionMethodSignatures .get (declaringClass );
291
+ if (reflectionSignatures != null ) {
292
+ MethodSignature methodSignature = new MethodSignature (method );
293
+ if (reflectionSignatures .contains (methodSignature )) {
294
+ return new MethodInfo (DynamicAccessKind .Reflection , getClassName (declaringClass ) + "#" + methodSignature );
295
+ }
254
296
}
255
297
256
- String methodName = method . getName ( );
257
- Signature signature = method . getSignature ();
258
- List < Class <?>> paramList = new ArrayList <>( );
259
- for ( int i = 0 ; i < signature . getParameterCount ( false ); i ++ ) {
260
- JavaType type = signature . getParameterType ( i , method . getDeclaringClass () );
261
- paramList . add ( OriginalClassProvider . getJavaClass ( type ));
298
+ Set < MethodSignature > resourceSignatures = resourceMethodSignatures . get ( declaringClass );
299
+ if ( resourceSignatures != null ) {
300
+ MethodSignature methodSignature = new MethodSignature ( method );
301
+ if ( resourceSignatures . contains ( methodSignature ) ) {
302
+ return new MethodInfo ( DynamicAccessKind . Resource , getClassName ( declaringClass ) + "#" + methodSignature );
303
+ }
262
304
}
263
- Class <?>[] paramTypes = paramList .toArray (new Class <?>[0 ]);
264
- MethodSignature methodSignature = new MethodSignature (methodName , paramTypes );
265
-
266
- if (reflectionMethodSignatures .containsKey (declaringClass ) &&
267
- reflectionMethodSignatures .get (declaringClass ).contains (methodSignature )) {
268
- return new MethodInfo (DynamicAccessKind .Reflection , getClassName (declaringClass ) + "#" + methodSignature );
269
- } else if (resourceMethodSignatures .containsKey (declaringClass ) &&
270
- resourceMethodSignatures .get (declaringClass ).contains (methodSignature )) {
271
- return new MethodInfo (DynamicAccessKind .Resource , getClassName (declaringClass ) + "#" + methodSignature );
272
- } else if (foreignMethodSignatures .containsKey (declaringClass ) &&
273
- foreignMethodSignatures .get (declaringClass ).contains (methodSignature )) {
274
- return new MethodInfo (DynamicAccessKind .Foreign , getClassName (declaringClass ) + "#" + methodSignature );
305
+
306
+ Set <MethodSignature > foreignSignatures = foreignMethodSignatures .get (declaringClass );
307
+ if (foreignSignatures != null ) {
308
+ MethodSignature methodSignature = new MethodSignature (method );
309
+ if (foreignSignatures .contains (methodSignature )) {
310
+ return new MethodInfo (DynamicAccessKind .Foreign , getClassName (declaringClass ) + "#" + methodSignature );
311
+ }
275
312
}
276
313
277
314
return null ;
@@ -332,6 +369,17 @@ private static class MethodSignature {
332
369
this .paramTypes = paramTypes ;
333
370
}
334
371
372
+ MethodSignature (ResolvedJavaMethod method ) {
373
+ this .name = method .getName ();
374
+ Signature signature = method .getSignature ();
375
+ List <Class <?>> paramList = new ArrayList <>();
376
+ for (int i = 0 ; i < signature .getParameterCount (false ); i ++) {
377
+ JavaType type = signature .getParameterType (i , method .getDeclaringClass ());
378
+ paramList .add (OriginalClassProvider .getJavaClass (type ));
379
+ }
380
+ paramTypes = paramList .toArray (new Class <?>[0 ]);
381
+ }
382
+
335
383
@ Override
336
384
public boolean equals (Object o ) {
337
385
if (this == o ) {
0 commit comments