Plugin not unload-safe because class loader cannot be unloaded
已回答
Hello,
I'm developing the HasteIt plugin for IDEA-based IDEs and I'm trying to figure out, why my plugin can't be unloaded correctly. The log show the following message:
> Plugin de.lukweb.hasteit is not unload-safe because class loader cannot be unloaded
My plugin dependens on another Gradle module called ShareBase to share code between two plugins (HasteIt and DiscordBeam), could this cause the class loader problem? Or is there another method to support code sharing and dynamic reloading?
Best regards,
Lukas
请先登录再写评论。
I have the same issue. I debugged `runIde` and found that my plugin class loader has tons of referring objects and all of them are from `kotlinx.serializer`. Therefore class loader can't unload and dynamic plugin doesn't work.
Try setting registry option ide.plugins.snapshot.on.unload.fail=true and set -XX:+UnlockDiagnosticVMOptions in VM options, you'll get memory snapshot to trace why it failed exactly. Please note that 2020.1 contains a number of known platform issues around unloading that can't be fixed on plugin side.
See also https://www.jetbrains.org/intellij/sdk/docs/basics/ide_development_instance.html#enabling-auto-reload
Thanks for your help Yann.
It took a little bit of time for me to find the location of memory dumps, that's why I thought it would be good to share this knowledge.
You can find the dumps (example name: `unload-de.lukweb.hasteit-31.05.2020_18.23.48.hprof)` in the most cases in your home / user folder. See DynamicPlugins.kt:467 for more information.
Thanks, the dump location is now logged in idea.log and also shown as notification in UI.
Yann Cebron Any tips on what to look in the `.hprof` to determine why the class loader cannot be unloaded?
Figured it out
Step 1
build.gradle.kts
Step 2
Run Plugin
run configuration. (Debug won’t work)ide.plugins.snapshot.on.unload.fail
Tip:
cmd+shift+a
Step 3
buildPlugin
Gradle task.Run > Run Plugin
tool window.idea.log
tab.all
.idea.log
tab.Dynamic plugins cannot reload if they use native dependencies or if a native dependency references something from the plugin.
From above we can see that our
ActionGroup
class is being referenced from the JNI, which prevents thePluginClassLoader
from being GC’d.This is because of the native code that controls the macOS menubar.
src/resources/META-INF/plugin.xml
So the problem is that plugins cannot reload if they modify the MainMenu.
If we don’t add to
MainMenu
, then our plugin reloads fine.[Edit] I have no idea why this is downvoted, but it appears that it didn't work for someone. Please let me know if you find something to be improved in this workflow.
Original post:
Vaughan Rouesnel What I recently did, was (because Dmitry Jemerov showed that he used it) to install YourKit (I have also tried with Eclipse MAT, IntelliJ and visualvm but none worked) which has a free trial, open the hprof file, go to Class loader, find the class loader which references your plugin things and click Paths from GC Roots. The classes that are mentioned there, were not unloaded successfully for whatever reason. (However, even on a partially successful unload, I see classes present here, so not sure what that means).
It was largely trial and error for me though, and reasoning about code (e.g., need to make sure to stop long-running coroutines, and pay attention to the 'Stateful extension' inspection), so not sure if there's a better way.
Also make sure to use latest 211 EAP, that fixed a lot of issues for me.
See https://youtrack.jetbrains.com/issue/IDEA-240845 about main menu issue
For reference, see https://plugins.jetbrains.com/docs/intellij/dynamic-plugins.html#troubleshooting on how to diagnose leaks.
Hi, I'm running into the same problem with some code that's basically a Kotlin'ized version of the comparing references sample. The CriQuickFix private static class from the java example is now an object member
After setting everything up per the notes, it appears that the offending JNI ref is that object, but not sure why that would have any native dependencies. It's the Java code, transformed to kotlin on paste with a little cleanup
Erich Oliphant, please use `class` instead of `object`
Hi, I actually tried that and had gotten it to work. But I was still having intermittent issues, with "Sticky Class" as the root vs JNI. It appears that (for inspections at least) you can't have a file in an active tab that triggers the inspection when you nav back to IntelliJ. If I say click to the README, build the plugin, jump back to IJ, then click Offender.java, reload seems to work just fine