Introduce VarHandle 9 stub#15486
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR introduces a compile‐time VarHandle stub for Java 8 and a runtime fallback to use real VarHandle on Java 9+ when Unsafe is unavailable, restoring JIT optimizations for buffer and ref-count accesses.
- Added a new
varhandle‐stubmodule that definesjava.lang.invoke.VarHandlestubs for Java 8 compilation. - Updated
PlatformDependentto detect and enable VarHandle support and exposedfindVarHandleOfIntField. - Extended
ReferenceCountUpdaterandAbstractReferenceCountedByteBufto use VarHandle as a fallback for managing reference counts.
Reviewed Changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| varhandle-stub/src/main/java/java/lang/invoke/package-info.java | New package-info documenting unstable stub API |
| varhandle-stub/src/main/java/java/lang/invoke/VarHandle.java | Stub implementation of VarHandle with core methods |
| varhandle-stub/pom.xml | POM for the stub module |
| pom.xml | Registered the new varhandle-stub module |
| common/src/main/java/io/netty/util/internal/VarHandleFactory.java | Factory to look up real VarHandle via MethodHandles |
| common/src/main/java/io/netty/util/internal/ReferenceCountUpdater.java | Added VarHandle-based fallback paths in ref-count operations |
| common/src/main/java/io/netty/util/internal/PlatformDependent.java | Detects VarHandle support, removes ordering methods, adds finder |
| common/pom.xml | Added provided‐scope dependency on netty-varhandle-stub |
| buffer/src/main/java/io/netty/buffer/AbstractReferenceCountedByteBuf.java | Integrated VarHandle into bytebuf ref-count logic |
| buffer/pom.xml | Added provided‐scope dependency on netty-varhandle-stub |
Comments suppressed due to low confidence (2)
common/src/main/java/io/netty/util/internal/PlatformDependent.java:612
- Consider adding unit tests for findVarHandleOfIntField to verify behavior both when VarHandle is enabled and disabled, ensuring coverage of fallback logic.
public static VarHandle findVarHandleOfIntField(Class<?> type, String fieldName) {
common/src/main/java/io/netty/util/internal/PlatformDependent.java:612
- Add a Javadoc comment describing the purpose, parameters, and return value of findVarHandleOfIntField to improve code discoverability and clarity.
public static VarHandle findVarHandleOfIntField(Class<?> type, String fieldName) {
|
on with this PR, with with unsafe working i.e. which shows that |
|
@franz1981 there are some failing tests... PTAL |
|
@normanmaurer I've added another commit to handle the byte[] case too. |
5728f71 to
2fabb11
Compare
|
@normanmaurer @chrisvest I see that I could remove the |
6937238 to
c8f73b7
Compare
|
@normanmaurer I had to remove but I'm still getting some error which I cannot reproduce locally e.g. now investigating, since I see that the public void setInitialValue(T instance) {
final long offset = unsafeOffset();
if (offset == -1) {
Object vho = varHandleUpdater();
int initialValue = initialValue();
if (vho != null) {
VarHandle vh = (VarHandle) vho;
vh.set(instance, (int) initialValue); // <-------- THIS IS THE ERROR
VarHandle.storeStoreFence();
} else {
updater().set(instance, initialValue);
}
} else {
PlatformDependent.safeConstructPutInt(instance, offset, initialValue());
}
}which enforce the "right" type at runtime, not at compile time. At compile time the invocation is using I'll come up with a solution for that 👍 |
|
There's still something which is surprising: if I write a sample program (using
|
|
On the CI I'm still getting hit by the same error on JDK 24-25 but the signature now is @Override
protected void setVarHandleRefCnt(VarHandle vh, AbstractReferenceCountedByteBuf instance, int refCnt) {
vh.set(instance, refCnt);
}Looking at |
|
It could be that the issue comes from the fact that the
|
|
Is it worthy to give it a shot @derklaro thanks for the suggestion - although "in theory" the stub shouldn't even be loaded and from the invocation pov (at byte level) it shouldn't matter |
|
@derklaro and I believe you're right I just checked a clean example and the bytecode of a proper |
|
If you go the stubbing route here, maybe it's best to just combine it with the JFR stub instead of having two modules. There might come a point where we want eg a StackWalker stub too. |
|
thanks for looking at it @yawkat I'm checking what I can do about it - unless you know But I agree that we would like to have a single stubs modules at this point |
|
@franz1981 I quickly skimmed through the jdk source and found that methods annotated with |
|
good catch, making the stub method |
|
I've added a fix - it was a broken benchmark - now performance is as expected, see dfa88e72a908498f2f940eb7e5137c039fb952f4 |
|
We can leave VarHandle be for NI for now, but the new Configuration-based AIFU initialization has the same problem that NI won't be able to infer the field it belongs to. |
|
Why? When unsafe or VarHandle won't be available it should be known statically and the updater is allocated without reflection and using constants Check the latest commit which perform the updater allocation in place |
|
Ahh you're right, I thought it was a local method call, not a static import. |
|
@franz1981 so this is ready for review ? |
|
Yep @normanmaurer now adding one condition and some doc but yep |
normanmaurer
left a comment
There was a problem hiding this comment.
Generally speaking looks good and awesome work. Please add some comments / javadocs to explain why we need this
|
PTAL @normanmaurer added some docs in the varhandle stub to explain why it is how it is and what devs should do while using it |
Motivation: Unsafe unavailability prevent some basic JIT optimizations while accessing buffers and reference counters, causing some pretty severe performance regression Modifications: Expose a VarHandle's 9 stub to enable Ja +9 to use it, if Unsafe is unavailable Result: Fixes netty#15485
|
If it's ready to go it can unblock #15504 ptal @chrisvest or @normanmaurer |
chrisvest
left a comment
There was a problem hiding this comment.
Excellent work, @franz1981 👍
|
Thanks @chrisvest 🙏 so, ready to go? |
|
@franz1981 squash and merge when happy with it |
|
@normanmaurer remember, right now I have disabled var handle if unsafe is there, since is a more performant option, but for io_uring maybe you still want to use it even if unsafe is available 🙏 |
Yep will do once this one is merged |

Motivation:
Unsafe unavailability prevent some basic JIT optimizations while accessing buffers and reference counters, causing some pretty severe performance regression
Modifications:
Expose a VarHandle's 9 stub to enable Ja +9 to use it, if Unsafe is unavailable
Result:
Fixes #15485