1818import static org .objectweb .asm .Opcodes .INVOKESTATIC ;
1919import static org .objectweb .asm .Opcodes .INVOKEVIRTUAL ;
2020import static org .objectweb .asm .Opcodes .IRETURN ;
21+ import static org .objectweb .asm .Opcodes .L2I ;
2122import static org .objectweb .asm .Opcodes .NEW ;
2223import static org .objectweb .asm .Opcodes .PUTSTATIC ;
2324import 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