Skip to content

Commit 2b5956d

Browse files
committed
[GR-58553] Adapt NI agent for the new JDK release
PullRequest: graal/18922
2 parents 012da85 + 4bef9ea commit 2b5956d

File tree

2 files changed

+33
-13
lines changed

2 files changed

+33
-13
lines changed

substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/BreakpointInterceptor.java

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,22 +1194,21 @@ private static boolean methodTypeFromDescriptor(JNIEnvironment jni, JNIObjectHan
11941194
return true;
11951195
}
11961196

1197-
/**
1198-
* This method should be intercepted when we are predefining a lambda class. This is the only
1199-
* spot in the lambda-class creation pipeline where we can get lambda-class bytecode so the
1200-
* class can be predefined. We do not want to predefine all lambda classes, but only the ones
1201-
* that are actually created at runtime, so we have a method that checks wheter the lambda
1202-
* should be predefined or not.
1203-
*/
1204-
private static boolean onMethodHandleClassFileInit(JNIEnvironment jni, JNIObjectHandle thread, @SuppressWarnings("unused") Breakpoint bp, InterceptedState state) {
1197+
private record LambdaClassNameAndBytecode(String lambdaClassName, byte[] lambdaClassBytecode) {
1198+
}
1199+
1200+
private static LambdaClassNameAndBytecode getLambdaClassNameAndBytecodeFromThread(JNIEnvironment jni, JNIObjectHandle thread, int bytecodeArgumentIndex) {
1201+
LambdaClassNameAndBytecode emptyLambdaClassNameAndBytecode = new LambdaClassNameAndBytecode(null, null);
1202+
12051203
String className = Support.fromJniString(jni, getObjectArgument(thread, 1));
1204+
assert className != null;
12061205

12071206
if (LambdaUtils.isLambdaClassName(className)) {
12081207
if (shouldIgnoreLambdaClassForPredefinition(jni)) {
1209-
return true;
1208+
return emptyLambdaClassNameAndBytecode;
12101209
}
12111210

1212-
JNIObjectHandle bytesArray = getObjectArgument(thread, 3);
1211+
JNIObjectHandle bytesArray = getObjectArgument(thread, bytecodeArgumentIndex);
12131212
int length = jniFunctions().getGetArrayLength().invoke(jni, bytesArray);
12141213
byte[] data = new byte[length];
12151214

@@ -1222,9 +1221,29 @@ private static boolean onMethodHandleClassFileInit(JNIEnvironment jni, JNIObject
12221221
}
12231222

12241223
className += Digest.digest(data);
1225-
tracer.traceCall("classloading", "onMethodHandleClassFileInit", null, null, null, null, state.getFullStackTraceOrNull(), className, data);
1224+
return new LambdaClassNameAndBytecode(className, data);
12261225
}
12271226
}
1227+
1228+
return emptyLambdaClassNameAndBytecode;
1229+
}
1230+
1231+
/**
1232+
* This method should be intercepted on JDK 24 or later when we are predefining a lambda class.
1233+
* We do not want to predefine all lambda classes, but only the ones that are actually created
1234+
* at runtime, so we have a method that checks whether the lambda should be predefined or not.
1235+
*/
1236+
private static boolean makeHiddenClassDefiner(JNIEnvironment jni, JNIObjectHandle thread, @SuppressWarnings("unused") Breakpoint bp, InterceptedState state) {
1237+
LambdaClassNameAndBytecode lambdaClassNameAndBytecode = getLambdaClassNameAndBytecodeFromThread(jni, thread, 2);
1238+
return lambdaPredefinition(state, lambdaClassNameAndBytecode.lambdaClassName(), lambdaClassNameAndBytecode.lambdaClassBytecode());
1239+
}
1240+
1241+
private static boolean lambdaPredefinition(InterceptedState state, String className, byte[] data) {
1242+
if (className == null) {
1243+
return false;
1244+
}
1245+
1246+
tracer.traceCall("classloading", "lambdaPredefinition", null, null, null, null, state.getFullStackTraceOrNull(), className, data);
12281247
return true;
12291248
}
12301249

@@ -1923,7 +1942,8 @@ private static boolean allocateInstance(JNIEnvironment jni, JNIObjectHandle thre
19231942
};
19241943

19251944
private static final BreakpointSpecification[] CLASS_PREDEFINITION_BREAKPOINT_SPECIFICATIONS = {
1926-
optionalBrk("java/lang/invoke/MethodHandles$Lookup$ClassFile", "<init>", "(Ljava/lang/String;I[B)V", BreakpointInterceptor::onMethodHandleClassFileInit),
1945+
optionalBrk("java/lang/invoke/MethodHandles$Lookup", "makeHiddenClassDefiner",
1946+
"(Ljava/lang/String;[BZLjdk/internal/util/ClassFileDumper;I)Ljava/lang/invoke/MethodHandles$Lookup$ClassDefiner;", BreakpointInterceptor::makeHiddenClassDefiner)
19271947
};
19281948

19291949
private static BreakpointSpecification brk(String className, String methodName, String signature, BreakpointHandler handler) {

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/trace/ClassLoadingProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ void processEntry(EconomicMap<String, Object> entry, ConfigurationSet configurat
4242

4343
String function = (String) entry.get("function");
4444
List<?> args = (List<?>) entry.get("args");
45-
if ("onClassFileLoadHook".equals(function) || "onMethodHandleClassFileInit".equals(function)) {
45+
if ("onClassFileLoadHook".equals(function) || "lambdaPredefinition".equals(function)) {
4646
expectSize(args, 2);
4747
String nameInfo = (String) args.get(0);
4848
byte[] classData = asBinary(args.get(1));

0 commit comments

Comments
 (0)