On Mon, 8 Jun 2026 14:44:49 GMT, Chris Plummer <[email protected]> wrote:
> The PR resolves the issue JDI has with allowing collection of objects that > are returned by the JDI invoke API before the caller of the API has a chance > to call ObjectReference.disableCollection(). Details in the first comment. > > Consider this to be a prototype. I'm open to discussion on other possible > solutions. I also still need to update the JDI specs to reflect these changes. > > --------- > - [x] I confirm that I make this contribution in accordance with the [OpenJDK > Interim AI Policy](https://openjdk.org/legal/ai). The core issue here is that with modern collectors it is becoming more and more common for returned newly allocated objects to be collected before the debugger can call ObjectReference.disableCollection(). Historically JDI has assumed that since at the very least the thread used to do the invoke on has been suspended, a GC could not happen. That hasn't been true for a very long time, even with all threads suspended, and has resulted in ObjectCollectedExceptions turning up in many of our tests. These were for the most part test bugs since they never called ObjectReference.disableCollection(), but even if they do, there is still a chance of the object being collected before the call is made, and this is an issue for debuggers. Modern GCs have made this problem even worse. The main JDI APIs involved are following, all of which use the JDI invoker support (using JDI to invoke a method on the target JVM): - ObjectReference.invokeMethod() - ClassType.invokeMethod() - InterfaceType.invokeMethod() - ClassType.newInstance() Also the following two APIs, which currently are not addressed by this PR. These do not use the invoke API. - VirtualMachine.mirrorOf(String), which uses JDWP VirtualMachine.CreateString - ArrayType.newInstance The APIs which use the JDI invoke API can all be fixed by adding a new invoke flag called INVOKE_DISABLE_COLLECTION. This is in addition to the existing INVOKE_SINGLE_THREADED and INVOKE_NONVIRTUAL flags. This is what has been implemented in this PR. So the first question is whether this approach should be the one used, and if yes, how should we address the other two APIs. Most debuggers are already doing working around this issue by putting array and String allocation in a retry loop until ObjectReference.disableCollection() succeeds. This is not so bad since these APIs don't have side affects unlike the invoke APIs do. We could also create something like ArrayType.newInstanceDisableCollection, although the naming gets awkward. It's also easy to create JDWP VirutualMachine.CreateStringDisableCollection, but we would then need something like VirtualMachine.mirrorOf(String, boolean disableCollection) in order to use it from JDI. Another possible solution that would cover all 6 of these allocation API is to add a new API called something like VirtualMachine.DisableCollection. The name as given is a bit misleading. It would only disable collection on any ObjectReference returned by the above APIs. It's a bit risky, because the user may not be aware of all these API and possibly end up with memory leaks due to forgetting to call objectreference.enablecollection() (note, once the debugger detaches the references are released and the objects can be collected). We could also limit its use to allocated arrays and Strings, and leave the INVOKE_DISABLE_COLLECTION flag for when using the invoke APIs. And one more thing to point out about the INVOKE_DISABLE_COLLECTION flag. It not only impacts the returned ObjectReference, but if an exception is thrown, it disables collection on the ObjectReference representing the actual exception Object thrown. It is stored in the InvocationException object. So users need to be aware that if they use this flag and an exception is thrown, they need to call disableCollection() on the exception object or it won't be collected. We could use a different flag for the exception if desirable. The flags could be called something like INVOKE_DISABLE_COLLECTION_ON_RETURNED_OBJECT and INVOKE_DISABLE_COLLECTION_ON_EXCEPTION_OBJECT) ------------- PR Comment: https://git.openjdk.org/jdk/pull/31421#issuecomment-4650222280
