Race condition background loading CH extensions resulting in java.lang.LinkageError "duplicate class definition"
LadyCailinBot opened this issue ยท 4 comments
CMDHELPER-3179 - Reported by totemo
With reference to WORLDEDIT-3975, PaperSpigot sometimes fails to load WorldEdit, taking out dependent plugins like WorldGuard, and thus allowing the world to literally catch fire.
In the WorldEdit bug, it came up that Paper may be doing some async loading of classes in PluginClassLoader. Looking through all of the server logs where LinkageError comes up I noticed that CH loads extensions in the background.
Sometimes this results in a duplicate class definition error when loading the WorldEdit plugin. Sometimes, but not always, CommandHelper methods feature in the stack trace:
2019-08-03 04:16:31 | [RAW] Loading WorldEdit v7.0.1-SNAPSHOT;4579-c5f46d1
2019-08-03 04:16:32 | [RAW] Could not load class 'io.github.jbaero.skcompat.CHWorldEdit.sk_setblock'
2019-08-03 04:16:32 | [RAW] java.lang.LinkageError: loader (instance of org/bukkit/plugin/java/PluginClassLoader): attempted duplicate class definition for name: "com/sk89q/worldedit/world
/block/BlockStateHolder"
2019-08-03 04:16:32 | [RAW] at java.lang.ClassLoader.defineClass1(Native Method)
2019-08-03 04:16:32 | [RAW] at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
2019-08-03 04:16:32 | [RAW] at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
2019-08-03 04:16:32 | [RAW] at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:135)
2019-08-03 04:16:32 | [RAW] at org.bukkit.plugin.java.JavaPluginLoader.getClassByName(JavaPluginLoader.java:201)
2019-08-03 04:16:32 | [RAW] at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:96)
2019-08-03 04:16:32 | [RAW] at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:85)
2019-08-03 04:16:32 | [RAW] at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
2019-08-03 04:16:32 | [RAW] at java.lang.ClassLoader.loadClass(ClassLoader.java:411)
2019-08-03 04:16:32 | [RAW] at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
2019-08-03 04:16:32 | [RAW] at java.lang.Class.forName0(Native Method)
2019-08-03 04:16:32 | [RAW] at java.lang.Class.forName(Class.java:348)
2019-08-03 04:16:32 | [RAW] at com.laytonsmith.PureUtilities.Common.ClassUtils.forCanonicalName(ClassUtils.java:139)
2019-08-03 04:16:32 | [RAW] at com.laytonsmith.PureUtilities.Common.ClassUtils.forCanonicalName(ClassUtils.java:45)
2019-08-03 04:16:32 | [RAW] at com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.ClassReferenceMirror.loadClass(ClassReferenceMirror.java:65)
2019-08-03 04:16:32 | [RAW] at com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.ClassMirror.loadClass(ClassMirror.java:480)
2019-08-03 04:16:32 | [RAW] at com.laytonsmith.core.extensions.ExtensionManager.lambda$Initialize$0(ExtensionManager.java:449)
2019-08-03 04:16:32 | [RAW] at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1556)
2019-08-03 04:16:32 | [RAW] at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
2019-08-03 04:16:32 | [RAW] at com.laytonsmith.core.extensions.ExtensionManager.Initialize(ExtensionManager.java:440)
2019-08-03 04:16:32 | [RAW] at com.laytonsmith.commandhelper.CommandHelperPlugin$5.run(CommandHelperPlugin.java:289)
2019-08-03 04:16:32 | [RAW] Got request to register class com.sk89q.worldedit.bukkit.BukkitServerInterface with WorldEdit [com.sk89q.worldedit.extension.platform.PlatformManager@46058a34]
We have SKCompat (most recent version, SKCompat-3.1.0-b34.jar) and I suspect that CH and Paper are both attempting to load classes in such a way that there is this intermittent failure.
I've looked through the CH preferences and there does not appear to be an option to disable async loading of extensions.
So my questions are:
- Do you think that async extension loading might be the root of the problem with duplicate WorldEdit classes?
- Is there a way to force CH to load extensions synchronously?
- Will that work with Paper or will Paper's PluginClassLoader get upset that those classes are already loaded?
- And therefore is there a way to delay CH extension loading?
Comment by totemo
I should note that of the 73 plugins we currently run, only WorldEdit has suffered class loading problems, on 7 separate occasions now.
Comment by PseudoKnight
This seems likely, though unlucky. I didn't write the extension loading system, and I'm not sure about the technical details. However, because of the nature of this issue I pushed a change to load the classes synchronously. Let me know if you keep experiencing this, or after some time you haven't experienced this again.
Comment by totemo
Thanks, PseudoKnight. We'll update here when we have new information to report.
The updated CommandHelper is happy to load in testing, so it will be running in production in about 5 minutes from now. We were having problems every few days, so if we can go for a week or two without incident, I think that would confirm it.