JetBrainsRuntime icon indicating copy to clipboard operation
JetBrainsRuntime copied to clipboard

After migrating from travajdk to jbr17 redefineClasses fails with ObjectCollectedException

Open kochetkovSergeY opened this issue 1 year ago • 18 comments

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

kochetkovSergeY avatar Jan 11 '24 10:01 kochetkovSergeY

Or it's an openjdk issue?

kochetkovSergeY avatar Jan 11 '24 10:01 kochetkovSergeY

Are you using -XX:+AllowEnhancedClassRedefinition (it is not deafult in jbr17 as is in TravaJDK) ?

skybber avatar Jan 11 '24 10:01 skybber

@skybber yes, we have two settings -XX:+AllowEnhancedClassRedefinition -XX:HotswapAgent=fatjar

kochetkovSergeY avatar Jan 11 '24 11:01 kochetkovSergeY

Could you please create a minimal example reproducing this bug?

skybber avatar Jan 11 '24 13:01 skybber

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)

kochetkovSergeY avatar Jan 12 '24 09:01 kochetkovSergeY

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?

kochetkovSergeY avatar Jan 12 '24 09:01 kochetkovSergeY

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.

skybber avatar Jan 13 '24 15:01 skybber

Jvm crashes with this paramter -XX:-ClassUnloading on the first attempt to redefine class... hs_err_pid21268.log

kochetkovSergeY avatar Jan 17 '24 12:01 kochetkovSergeY

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?

skybber avatar Jan 17 '24 14:01 skybber

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.

skybber avatar Jan 17 '24 17:01 skybber

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.

I tied this, jvm not crashing now, but -XX:-ClassUnloading not helped at all, error still occuring

kochetkovSergeY avatar Jan 18 '24 10:01 kochetkovSergeY

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

kochetkovSergeY avatar Jan 18 '24 13:01 kochetkovSergeY

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.

skybber avatar Jan 18 '24 20:01 skybber

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

skybber avatar Jan 22 '24 09:01 skybber

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?

skybber avatar Jan 28 '24 18:01 skybber

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...

kochetkovSergeY avatar Jan 31 '24 10:01 kochetkovSergeY

@skybber @kochetkovSergeY the spring issue is https://github.com/HotswapProjects/HotswapAgent/issues/530 ?

cvictory avatar Feb 08 '24 02:02 cvictory

@cvictory Yes please.

skybber avatar Feb 08 '24 07:02 skybber

@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?

kochetkovSergeY avatar Mar 27 '24 12:03 kochetkovSergeY

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...

vprovodin avatar Mar 27 '24 12:03 vprovodin

oh now I understand, thank you, build number like hotfix version, this was the reason of misunderstanding:

image

kochetkovSergeY avatar Mar 29 '24 05:03 kochetkovSergeY