Skip to content

Commit 03dffb1

Browse files
authored
Run tests with jdk24 and 25-ea (#13824)
1 parent 5016efb commit 03dffb1

File tree

8 files changed

+90
-31
lines changed

8 files changed

+90
-31
lines changed

.github/workflows/build-common.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ jobs:
242242
- 17
243243
- 21
244244
- 23
245-
- 24-ea
245+
- 24
246+
- 25-ea
246247
vm:
247248
- hotspot
248249
- openj9
@@ -256,7 +257,11 @@ jobs:
256257
- true
257258
exclude:
258259
- vm: ${{ inputs.skip-openj9-tests && 'openj9' || '' }}
259-
- test-java-version: 24-ea
260+
- test-java-version: 23
261+
vm: hotspot
262+
- test-java-version: 24
263+
vm: openj9
264+
- test-java-version: 25-ea
260265
vm: openj9
261266
fail-fast: false
262267
steps:

custom-checks/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ dependencies {
1313

1414
otelJava {
1515
minJavaVersionSupported.set(JavaVersion.VERSION_17)
16+
// OtelInternalJavadocTest fails with 25-ea
17+
maxJavaVersionForTests.set(JavaVersion.VERSION_24)
1618
}
1719

1820
// We cannot use "--release" javac option here because that will forbid exporting com.sun.tools package.

docs/supported-libraries.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ These are the JVMs and operating systems that the integration tests are run agai
226226

227227
| JVM | Versions | OS |
228228
|-------------------------------------------------------------------------------------------|-------------------|-------------------|
229-
| [OpenJDK (Eclipse Temurin)](https://adoptium.net/) | 8, 11, 17, 21, 23 | [`ubuntu-latest`] |
229+
| [OpenJDK (Eclipse Temurin)](https://adoptium.net/) | 8, 11, 17, 21, 24 | [`ubuntu-latest`] |
230230
| [OpenJ9 (IBM Semeru Runtimes)](https://developer.ibm.com/languages/java/semeru-runtimes/) | 8, 11, 17, 21, 23 | [`ubuntu-latest`] |
231231

232232
## Disabled instrumentations

instrumentation/runtime-telemetry/runtime-telemetry-java17/javaagent/src/test/java/io/opentelemetry/instrumentation/javaagent/runtimemetrics/java17/JfrRuntimeMetricsTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ void shouldHaveDefaultMetrics() {
3535

3636
testing.waitAndAssertMetrics(
3737
"io.opentelemetry.runtime-telemetry-java17",
38-
metric -> metric.hasName("jvm.cpu.longlock"),
3938
metric -> metric.hasName("jvm.cpu.limit"),
4039
metric -> metric.hasName("jvm.cpu.context_switch"));
4140
}

instrumentation/xxl-job/xxl-job-1.9.2/javaagent/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ muzzle {
1111
}
1212
}
1313

14+
otelJava {
15+
// groovy does not support 25-ea
16+
maxJavaVersionForTests.set(JavaVersion.VERSION_24)
17+
}
18+
1419
dependencies {
1520
library("com.xuxueli:xxl-job-core:1.9.2") {
1621
exclude("org.codehaus.groovy", "groovy")

instrumentation/xxl-job/xxl-job-2.1.2/javaagent/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ muzzle {
1111
}
1212
}
1313

14+
otelJava {
15+
// groovy does not support 25-ea
16+
maxJavaVersionForTests.set(JavaVersion.VERSION_24)
17+
}
18+
1419
dependencies {
1520
library("com.xuxueli:xxl-job-core:2.1.2") {
1621
exclude("org.codehaus.groovy", "groovy")

instrumentation/xxl-job/xxl-job-2.3.0/javaagent/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ muzzle {
1111
}
1212
}
1313

14+
otelJava {
15+
// groovy does not support 25-ea
16+
maxJavaVersionForTests.set(JavaVersion.VERSION_24)
17+
}
18+
1419
dependencies {
1520
library("com.xuxueli:xxl-job-core:2.3.0") {
1621
exclude("org.codehaus.groovy", "groovy")

javaagent-tooling/javaagent-tooling-java9/src/main/java/io/opentelemetry/javaagent/tooling/SunMiscUnsafeGenerator.java

Lines changed: 65 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
1919
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
2020
import static org.objectweb.asm.Opcodes.IRETURN;
21+
import static org.objectweb.asm.Opcodes.L2I;
2122
import static org.objectweb.asm.Opcodes.NEW;
2223
import static org.objectweb.asm.Opcodes.PUTSTATIC;
2324
import static org.objectweb.asm.Opcodes.RETURN;
@@ -82,21 +83,28 @@ private void addFields() {
8283
addField("ADDRESS_SIZE", int.class);
8384
}
8485

85-
private boolean hasSuitableField(String name, Class<?> type) {
86+
private Field findSourceField(String name) {
8687
try {
87-
Field field = internalUnsafeClass.getDeclaredField(name);
88-
return Modifier.isPublic(field.getModifiers()) && field.getType() == type;
88+
return internalUnsafeClass.getDeclaredField(name);
8989
} catch (NoSuchFieldException exception) {
90-
return false;
90+
return null;
9191
}
9292
}
9393

94+
private boolean isSuitableField(Field field, Class<?> type) {
95+
// jdk25 changes field type from int to long for offsets
96+
return field != null
97+
&& Modifier.isPublic(field.getModifiers())
98+
&& (field.getType() == type || (field.getType() == long.class && type == int.class));
99+
}
100+
94101
private void addField(String name, Class<?> type) {
95-
if (!hasSuitableField(name, type)) {
102+
Field field = findSourceField(name);
103+
if (!isSuitableField(field, type)) {
96104
throw new IllegalStateException(
97105
"Could not find suitable field for " + name + " " + Type.getDescriptor(type));
98106
}
99-
fields.add(new FieldDescriptor(name, type));
107+
fields.add(new FieldDescriptor(name, type, field.getType()));
100108
}
101109

102110
private void addMethods() {
@@ -231,14 +239,15 @@ private void addMethod(
231239
List<String> targetNameCandidates,
232240
Class<?> returnType,
233241
Class<?>... parameterTypes) {
234-
String targetName = null;
242+
Method target = null;
235243
for (String candidate : targetNameCandidates) {
236-
if (hasSuitableMethod(candidate, returnType, parameterTypes)) {
237-
targetName = candidate;
244+
Method method = findSourceMethod(candidate, parameterTypes);
245+
if (isSuitableMethod(method, returnType)) {
246+
target = method;
238247
break;
239248
}
240249
}
241-
if (targetName == null) {
250+
if (target == null) {
242251
if (optional) {
243252
return;
244253
}
@@ -248,18 +257,27 @@ private void addMethod(
248257
+ " "
249258
+ Type.getMethodDescriptor(Type.getType(returnType), toTypes(parameterTypes)));
250259
}
251-
methods.add(new MethodDescriptor(name, targetName, returnType, parameterTypes));
260+
methods.add(
261+
new MethodDescriptor(
262+
name, target.getName(), returnType, target.getReturnType(), parameterTypes));
252263
}
253264

254-
private boolean hasSuitableMethod(String name, Class<?> returnType, Class<?>... parameterTypes) {
265+
private Method findSourceMethod(String name, Class<?>... parameterTypes) {
255266
try {
256-
Method method = internalUnsafeClass.getDeclaredMethod(name, parameterTypes);
257-
return Modifier.isPublic(method.getModifiers()) && method.getReturnType() == returnType;
258-
} catch (NoSuchMethodException e) {
259-
return false;
267+
return internalUnsafeClass.getDeclaredMethod(name, parameterTypes);
268+
} catch (NoSuchMethodException exception) {
269+
return null;
260270
}
261271
}
262272

273+
private boolean isSuitableMethod(Method method, Class<?> returnType) {
274+
// jdk25 changes method return type from int to long for methods returning fields offsets
275+
return method != null
276+
&& Modifier.isPublic(method.getModifiers())
277+
&& (method.getReturnType() == returnType
278+
|| (method.getReturnType() == long.class && returnType == int.class));
279+
}
280+
263281
private static Type[] toTypes(Class<?>... classes) {
264282
Type[] result = new Type[classes.length];
265283
for (int i = 0; i < classes.length; i++) {
@@ -270,25 +288,33 @@ private static Type[] toTypes(Class<?>... classes) {
270288

271289
private static class FieldDescriptor {
272290
final String name;
273-
final Class<?> type;
291+
final Class<?> targetType;
292+
final Class<?> sourceType;
274293

275-
FieldDescriptor(String name, Class<?> type) {
294+
FieldDescriptor(String name, Class<?> targetType, Class<?> sourceType) {
276295
this.name = name;
277-
this.type = type;
296+
this.targetType = targetType;
297+
this.sourceType = sourceType;
278298
}
279299
}
280300

281301
private static class MethodDescriptor {
282302
final String name;
283303
final String targetName;
284-
final Class<?> returnType;
304+
final Class<?> targetReturnType;
305+
final Class<?> sourceReturnType;
285306
final Class<?>[] parameterTypes;
286307

287308
MethodDescriptor(
288-
String name, String targetName, Class<?> returnType, Class<?>[] parameterTypes) {
309+
String name,
310+
String targetName,
311+
Class<?> targetReturnType,
312+
Class<?> sourceReturnType,
313+
Class<?>[] parameterTypes) {
289314
this.name = name;
290315
this.targetName = targetName;
291-
this.returnType = returnType;
316+
this.targetReturnType = targetReturnType;
317+
this.sourceReturnType = sourceReturnType;
292318
this.parameterTypes = parameterTypes;
293319
}
294320
}
@@ -329,16 +355,18 @@ private byte[] getBytes() {
329355
cv.visitField(
330356
ACC_PUBLIC | ACC_STATIC | ACC_FINAL,
331357
field.name,
332-
Type.getDescriptor(field.type),
358+
Type.getDescriptor(field.targetType),
333359
null,
334360
null);
335361
fv.visitEnd();
336362
}
337363

338364
for (MethodDescriptor method : methods) {
339365
Type[] parameters = toTypes(method.parameterTypes);
340-
Type returnType = Type.getType(method.returnType);
366+
Type returnType = Type.getType(method.targetReturnType);
341367
String descriptor = Type.getMethodDescriptor(returnType, parameters);
368+
String sourceDescriptor =
369+
Type.getMethodDescriptor(Type.getType(method.sourceReturnType), parameters);
342370
MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, method.name, descriptor, null, null);
343371
mv.visitCode();
344372
mv.visitFieldInsn(
@@ -352,8 +380,13 @@ private byte[] getBytes() {
352380
INVOKEVIRTUAL,
353381
Type.getInternalName(internalUnsafeClass),
354382
method.targetName,
355-
descriptor,
383+
sourceDescriptor,
356384
false);
385+
if (method.targetReturnType != method.sourceReturnType
386+
&& method.targetReturnType == int.class
387+
&& method.sourceReturnType == long.class) {
388+
mv.visitInsn(L2I);
389+
}
357390
mv.visitInsn(returnType.getOpcode(IRETURN));
358391
mv.visitMaxs(0, 0);
359392
mv.visitEnd();
@@ -385,8 +418,13 @@ private byte[] getBytes() {
385418
GETSTATIC,
386419
Type.getInternalName(internalUnsafeClass),
387420
field.name,
388-
Type.getDescriptor(field.type));
389-
mv.visitFieldInsn(PUTSTATIC, UNSAFE_NAME, field.name, Type.getDescriptor(field.type));
421+
Type.getDescriptor(field.sourceType));
422+
if (field.sourceType != field.targetType
423+
&& field.targetType == int.class
424+
&& field.sourceType == long.class) {
425+
mv.visitInsn(L2I);
426+
}
427+
mv.visitFieldInsn(PUTSTATIC, UNSAFE_NAME, field.name, Type.getDescriptor(field.targetType));
390428
}
391429

392430
mv.visitInsn(RETURN);

0 commit comments

Comments
 (0)