-
Bug
-
Resolution: Unresolved
-
Minor
-
None
-
None
-
None
-
CraftBukkit version 3168-Spigot-a483d2c-bc00005 (MC: 1.17) (Implementing API version 1.17-R0.1-SNAPSHOT)
-
Yes
tl;dr: After the "automatic library support" commit to Bukkit, the plugin class loader now completely closes and uncaches all plugins immediately on shutdown, making them inaccessible in onDisable() in places they previously were accessible.
This is a breaking bug for Citizens.
The loose summary of how things are laid out is:
- Citizens is the base plugin, that provides NPCs
- Other plugins (such as Sentinel, which will be the example) function as addons, that add additional features to NPCs
- Sentinel has a Depend on Citizens listed in its plugin.yml, so that it loads immediately after Citizens and can register its addon data into Citizens
- The secondary result of depends is that shutdown order is reversed - Sentinel shuts down before Citizens does.
- Citizens auto-saves all data in its onDisable()
- Because Sentinel has registered addon data into Citizens, Citizens must save Sentinel's data during its save cycle.
- This means that in the Citizens onDisable(), Citizens must reference the Sentinel classes.
On earlier versions (Spigot 1.16.5 builds dated prior to May 14th, or 1.15.2/etc older versions, throughout basically all history back to 2012 Bukkit versions when Citizens was started), this worked as expected.
However, starting approximately May 14th, when the "automatic library support" commits were published - ref
https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/commits/146a7e4bd764990c56bb326643e92eb69f24d27e#src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java - this stopped functioning. References from Citizens to Sentinel classes now fail with a classloader error:
[06:22:01] [Server thread/ERROR]: Error occurred while disabling Citizens v2.0.28-SNAPSHOT (build 2333) (Is it up to date?)
java.lang.IllegalStateException: zip file closed
at java.util.zip.ZipFile.ensureOpen(ZipFile.java:828) ~[?:?]
at java.util.zip.ZipFile.getEntry(ZipFile.java:327) ~[?:?]
at java.util.jar.JarFile.getEntry(JarFile.java:513) ~[?:?]
at java.util.jar.JarFile.getJarEntry(JarFile.java:468) ~[?:?]
at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:154) ~[spigot-1.17.jar:3168-Spigot-a483d2c-bc00005]
at java.lang.ClassLoader.loadClass(ClassLoader.java:586) ~[?:?]
at org.bukkit.plugin.java.PluginClassLoader.loadClass0(PluginClassLoader.java:104) ~[spigot-1.17.jar:3168-Spigot-a483d2c-bc00005]
at org.bukkit.plugin.java.PluginClassLoader.loadClass(PluginClassLoader.java:99) ~[spigot-1.17.jar:3168-Spigot-a483d2c-bc00005]
at java.lang.ClassLoader.loadClass(ClassLoader.java:519) ~[?:?]
at java.lang.Class.forName0(Native Method) ~[?:?]
at java.lang.Class.forName(Class.java:466) ~[?:?]
at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:114) ~[?:?]
at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:125) ~[?:?]
at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49) ~[?:?]
at sun.reflect.annotation.AnnotationParser.parseSig(AnnotationParser.java:440) ~[?:?]
at sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:242) ~[?:?]
at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:121) ~[?:?]
at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:73) ~[?:?]
at java.lang.reflect.Field.declaredAnnotations(Field.java:1205) ~[?:?]
at java.lang.reflect.Field.declaredAnnotations(Field.java:1203) ~[?:?]
at java.lang.reflect.Field.getAnnotation(Field.java:1170) ~[?:?]
at net.citizensnpcs.api.persistence.PersistenceLoader.getFieldsFromClass(PersistenceLoader.java:361) ~[?:?]
at net.citizensnpcs.api.persistence.PersistenceLoader.getFields(PersistenceLoader.java:345) ~[?:?]
General hoped-for solution would be correcting it to not unload plugin jars until after ALL plugins are shutdown, rather than individual unloading each jar as the plugin unloads.