[SPIGOT-7145] PluginClassLoader does not re-open JarFile upon enabling a previously disabled JavaPlugin Created: 27/Aug/22  Updated: 25/Dec/24

Status: Open
Project: Spigot
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Minor
Reporter: Prodigy Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None
Environment:

While the test environment has Paper and PlugManX, the source code links below indicate that this continues to be a problem on the master branch


Attachments: File closed-jar-example-1.0.0.jar    
Version: This server is running Paper version git-Paper-788 (MC: 1.16.5) (Implementing API version 1.16.5-R0.1-SNAPSHOT)
Plugin: PlugManX
Guidelines Read: Yes

 Description   

Reproducible example (see attached plugin jar): 

  • onEnable: Attempt to do Class#forName(String) for some class that is not present on the classpath (in a try/catch for ClassNotFoundException)
  • When the server starts and calls onEnable, JarFile will be open, so no IllegalStateException is thrown from PluginClassLoader
  • Disable the plugin. This results in JarFile#close
  • Enable the plugin. The same Class#forName(String) call will trigger PluginClassLoader#findClass(String). Now, however, jar is closed, so an IllegalStateException is thrown

 

This is caused by the same PluginClassLoader being used in #enablePlugin, even after a call to #close.

 

Further, no attempt is made to re-open the plugin JarFile on re-enable, resulting in this IllegalStateException

 

java.lang.IllegalStateException: zip file closed
    at java.util.zip.ZipFile.ensureOpen(Unknown Source)
    at java.util.zip.ZipFile.getEntry(Unknown Source)
    at java.util.jar.JarFile.getEntry(Unknown Source)
    at java.util.jar.JarFile.getJarEntry(Unknown Source)
    at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:167)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at org.bukkit.plugin.java.PluginClassLoader.loadClass0(PluginClassLoader.java:119)
    at org.bukkit.plugin.java.PluginClassLoader.loadClass(PluginClassLoader.java:114)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Unknown Source)
    at io.github.iprodigy.bugreport.PluginClassLoaderClosedJarFileExample.onEnable(PluginClassLoaderClosedJarFileExample.java:10)
    at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:263)
    at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:370)
    at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:500)

 

If this is accepted as a bug, I can submit a potential patch for consideration.



 Comments   
Comment by md_5 [ 12/Sep/22 ]

That doesn't help, the loader relies both on the JarFile and the parent URLs to function correctly.

Comment by Prodigy [ 11/Sep/22 ]

I am trying to allow the plugin to be disabled & then enabled: plugman disable ClosedJarExample, plugman enable ClosedJarExample 

And yes, URLClassLoader doesn't have a re-open method, but one could be added to PluginClassLoader (which would require the JarFile field to be made non-final)

Comment by md_5 [ 11/Sep/22 ]

I also don't see how you can fix this without just not closing the classloader on disable, since URLClassLoader doesn't support reopening.

If you do have a fix perhaps submit it for consideration

Comment by md_5 [ 11/Sep/22 ]

I'm not sure this is how the API is meant to be used, since you're keeping around a leaking Plugin instance.

What exactly are you trying to do? Clearly not reload the plugin, since this wouldn't do that

Generated at Tue Apr 15 09:10:37 UTC 2025 using Jira 10.3.3#10030003-sha1:d220e3fefc8dfc6d47f522d3b9a20c1455e12b7b.