Skip to content

sun.misc.Unsafe deprecations in Java 24 #1803

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
eygraber opened this issue Apr 25, 2025 · 5 comments
Open

sun.misc.Unsafe deprecations in Java 24 #1803

eygraber opened this issue Apr 25, 2025 · 5 comments
Assignees
Labels

Comments

@eygraber
Copy link

I started getting a lot of deprecation warnings after updating to Java 24.

WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::objectFieldOffset has been called by net.bytebuddy.dynamic.loading.ClassInjector$UsingUnsafe$Dispatcher$CreationAction (file:/home/eli/.gradle/caches/8.14/transforms/80f1719e28957c8fbfa3503f6a13649f/transformed/byte-buddy-1.17.5.jar)
WARNING: Please consider reporting this to the maintainers of class net.bytebuddy.dynamic.loading.ClassInjector$UsingUnsafe$Dispatcher$CreationAction
WARNING: sun.misc.Unsafe::objectFieldOffset will be removed in a future release
@raphw
Copy link
Owner

raphw commented Apr 26, 2025

This means that Byte Buddy is likely used in a way that uses Unsafe. Typically for loading classes. This can likely be substituted by using method handles, but this is responsibility of the user.

I'd suggest investigating the used ClassLoadingStrategy.

@raphw raphw self-assigned this Apr 26, 2025
@raphw raphw added the question label Apr 26, 2025
@eygraber
Copy link
Author

Oh interesting, so it's being logged as coming from Byte Buddy, but not it isn't actually?

@raphw
Copy link
Owner

raphw commented Apr 27, 2025

It's used by net.bytebuddy.dynamic.loading.ClassInjector$UsingUnsafe, but it can of course be resolved by using a different ClassInjector.

@dogourd
Copy link

dogourd commented May 6, 2025

Some of ByteBuddy's default configurations implicitly use UsingReflection, which can be seen from the following call path:

new AgentBuilder.Default() -> 
new InitializationStrategy.SelfInjection.Split() -> 
new NexusAccess() -> 
NexusAccess.<clinit> -> 
private static final Dispatcher DISPATCHER = doPrivileged(Dispatcher.CreationAction.INSTANCE) -> 
new ClassInjector.UsingReflection()

When users use new AgentBuilder.Default(), the API itself doesn’t make it obvious that it will eventually rely on Unsafe.

Even if the user tries to express intent to avoid those APIs (e.g., via disableClassFormats), the underlying methods are still called during object construction.

This leaves users with no choice but to dig into the internals and potentially extend AgentBuilder.Default and override its constructor just to work around it.

After reviewing the comments before, it seems most of the warnings point to the use of objectFieldOffset. Upon investigation, ByteBuddy uses this to determine the memory layout of the AccessibleObject.offset, and then sets it via Unsafe to bypass modern JVM restrictions on reflective access. From what I can tell, this logic was likely introduced due to JPMS. Because of module visibility constraints, ByteBuddy gave up on using Field.setAccessible altogether.

However, I think this behavior could be improved—perhaps ByteBuddy should attempt setAccessible first before pessimistically falling back to Unsafe. After all, users can make the necessary JPMS adjustments via --add-opens or at runtime using Instrumentation.redefineModule, which would allow setAccessible to work without error.

To go a step further: if ByteBuddy detects the presence of an Instrumentation instance, maybe it could silently make the required module visibility changes on its own to allow access to jdk.internal.misc.

Finally, even with the latest Java versions, I personally think it's a bit unfortunate to completely abandon UsingUnsafe. Compared to UsingLookup, which can only inject classes into existing packages, UsingUnsafe allows injecting into entirely new packages. In that sense, UsingUnsafe is still the more powerful option.

@raphw
Copy link
Owner

raphw commented May 6, 2025

You can set -Dnet.bytebuddy.safe=true already to avoid Byte Buddy making an attempt. Once the possibility goes away, Byte Buddy will simply fail upon attempting to use reflection, then you will have to override manually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants