JetBrainsRuntime
JetBrainsRuntime copied to clipboard
After migrating from travajdk to jbr17 redefineClasses fails with ObjectCollectedException
I'm trying to reload classes multiple times, every time I'm attaching and disposing jvm again, it works fine for a some time but some time later it throws ObjectCollectedException:
pseudo code for every reload step:
jvm.attach(...);
List<ReferenceType> classTypes = vm.classesByName(className);
classTypes.forEach(classType->{
try {
Map<ReferenceType, byte[]> map = new HasMap<>();
map.put(classType, getNewClassBytes(className));
jvm.redefineClasses(map);
}
catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
});
jvm.dispose();
Could VirtualMachine.classesByName return collected ClassType-s?
error stack:
Caused by: com.sun.jdi.ObjectCollectedException
at jdk.jdi/com.sun.tools.jdi.JDWPException.toJDIException(JDWPException.java:55)
at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:433)
Error not cccuring if I remove jvm.attach and jvm.dispose calls, but i want to free up port for debug purposes for example
enviroment: latest jbr 17 latest hotswap-agent.jar built from master branch
Or it's an openjdk issue?
Are you using -XX:+AllowEnhancedClassRedefinition
(it is not deafult in jbr17 as is in TravaJDK) ?
@skybber yes, we have two settings -XX:+AllowEnhancedClassRedefinition -XX:HotswapAgent=fatjar
Could you please create a minimal example reproducing this bug?
it will take some time (not fast), but in debug i saw that VirtualMachine.classesByName returned collected Classtype (there is an error in toString() call)
I think the problem is in dispose method, the doc says:
Garbage collection is re-enabled in all cases where it was disabled through ObjectReference.disableCollection.
But with -XX:+AllowEnhancedClassRedefinition
it shouldn't collect ClassType?
If -XX:+AllowEnhancedClassRedefinition
is used, the redefinition of class C
to C'
generates a new instance (of java.lang.Class) for class C'
and updates all references to C
to now point to C'
. Therefore, in your specific scenario, there is likely a ReferenceType for the old class C
and another ReferenceType for the new class C'
. If -XX:-ClassUnloading
is not used, the subsequent full GC will reclaim the old instance of C'
. If you attempt to access the old ReferenceType, an ObjectCollectedException will be thrown. Ideally, DCEVM should keep older instances (instances of type Class) of C'
alive, but currently, they are collected since there are no references in the heap pointing to them.
Otherwise you can confirm this by using -XX:-ClassUnloading
.
Jvm crashes with this paramter -XX:-ClassUnloading
on the first attempt to redefine class...
hs_err_pid21268.log
It's hard to resolve the problem from supplied hs_err file, since stack mapping is missing. Could you please create an example reproducing this bug?
Jvm crashes with this paramter
-XX:-ClassUnloading
on the first attempt to redefine class... hs_err_pid21268.log
I'm able to reproduce the crash now. It seems, that it is related to G1 GC. You can try -XX:+UseSerialGC
as a workaround for now.
Jvm crashes with this paramter
-XX:-ClassUnloading
on the first attempt to redefine class... hs_err_pid21268.logI'm able to reproduce the crash now. It seems, that it is related to G1 GC. You can try
-XX:+UseSerialGC
as a workaround for now.
I tied this, jvm not crashing now, but -XX:-ClassUnloading
not helped at all, error still occuring
Could you please create a minimal example reproducing this bug?
@skybber
Here it is: https://github.com/kochetkovSergeY/jbr-issue-264-example
Repo contains two maven-spring-boot projects, one to start, second to reload class in the first
In this directory I starting the first app (with jbr and hotswap) with start.bat https://github.com/kochetkovSergeY/jbr-issue-264-example/tree/main/hotswap-app-to-update/src/test/java/com/example/hotswapagenterror
The second app is reloading class in cycle and later fails with error
Great job, thanks! It crashes on version 17.0.9 for me, but NO on the not yet released, new version with new dcevm fixes. It survives even 1k redefinitions. Fixes should be released in the next JBR releases.
There is a jbr branch with the patch available at:
https://github.com/JetBrains/JetBrainsRuntime/tree/vladimir.dvorak/JBR-6363
if you know how to build a JDK, it would be great if you could try it on your case, but don't feel it's necessary
I have reproduced this error even with the latest version of JBR. It seems that the error occurs when repeatedly connecting and disconnecting HotSwapper. Normally the debugger doesn't connect 100 times, so it hasn't appeared yet. Could you use Hotswapper as singleton with one connection as workaround?
We've already used this workaround, but we have cases when we need to connect to app debug port by other different apps, and there we have been catched this problem...
@skybber @kochetkovSergeY the spring issue is https://github.com/HotswapProjects/HotswapAgent/issues/530 ?
@cvictory Yes please.
@skybber I've seen that the bug was fixed in https://youtrack.jetbrains.com/issue/JBR-6648 but in newest jbr17 builds the problem from https://youtrack.jetbrains.com/issue/JBR-6648 is actual, forgot to merge?
BTW it was merged into https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr-release-17.0.10b1207.6 - targeted to be used by the latest 2024.1 IDEA release (see https://github.com/JetBrains/JetBrainsRuntime?tab=readme-ov-file#releases-based-on-jdk-17) There were no intentions to merge https://youtrack.jetbrains.com/issue/JBR-6648 into the previous releases i.e. 17.0.10-b1087, 17.0.10-b1000, 17.0.10-b829 etc...
oh now I understand, thank you, build number like hotfix version, this was the reason of misunderstanding: