[SPIGOT-3723] Adding additional source URLs to the plugin classloader doesn't work Created: 29/Dec/17 Updated: 29/Dec/17 Resolved: 29/Dec/17 |
|
Status: | Resolved |
Project: | Spigot |
Component/s: | None |
Affects Version/s: | None |
Fix Version/s: | None |
Type: | Bug | Priority: | Minor |
Reporter: | Luck | Assignee: | Unassigned |
Resolution: | Fixed | Votes: | 0 |
Labels: | None | ||
Environment: |
Windows. Latest Spigot. >version [10:39:43 INFO]: This server is running CraftBukkit version git-Spigot-b66ad9e-b5a10a9 (MC: 1.12.2) (Implementing API version 1.12.2-R0.1-SNAPSHOT) [10:39:43 INFO]: You are running the latest version
|
Description |
Hi.
I use the following code in my plugin to inject additional dependency jars at runtime.
This has worked fine in all Spigot/CraftBukkit builds until the recently. Now, when an injected class is referenced and loaded, a ClassNotFoundException is thrown.
https://hastebin.com/afiseluniw.sql
|
Comments |
Comment by Luck [ 29/Dec/17 ] |
I'd support any kind of API addition which allowed for the injection of extra sources at runtime. Admittedly, it's fairly uncommon for plugins to use this approach to dependencies - the vast majority using shading. However, in my case, doing things this way is the difference between distributing a 1mb jar and distributing a 10mb jar (with that size likely to grow in the future as more storage strategies are added)
> a gentle attempt at breaking the incorrect assumption that the PluginClassLoader is a URLClassLoader (for various reasons, it should no longer be, but that would probably break more plugins).
Interestingly, a similar thing has occurred following the release of Java 9. On prior versions, ClassLoader#getSystemClassLoader returned a subclass of URLClassLoader, but no longer does in J9 - and yeah, same outcome, stuff breaks.
https://blog.codefx.org/java/java-9-migration-guide/#Casting-To-URL-Class-Loader
Thanks for resolving the issue. |
Comment by md_5 [ 29/Dec/17 ] |
Efficiency issues (second dive into the jar), and a gentle attempt at breaking the incorrect assumption that the PluginClassLoader is a URLClassLoader (for various reasons, it should no longer be, but that would probably break more plugins). |
Comment by Luck [ 29/Dec/17 ] |
Yep, I understand - however, as you point out, there's no defined way to load additional dependencies. I have to resort to relying on reflection.
I've tried to do as you suggest by:
https://hastebin.com/lewaxumaze.scala However, this still results in the same error - as it seems the classloader of the calling class is still used instead.
It's not really viable to use reflection to interact with all dependencies. Instead of throwing an exception on PluginClassLoader line 122, could it not just delegate to super as it did previously?
In other words, what does this commit address?
I appreciate you can't support plugins which rely on implementation details, but I don't see why the change was necessary.
Thanks for your quick reply. |
Comment by md_5 [ 29/Dec/17 ] |
I don’t think this is a bug. 1) You’re using reflection to access methods that you shouldn’t be. 2) Bukkit makes no guarantees that the classloader used to load your plugin is even a URLClassloader. if you need to load libraries from external jars, you should be doing this by creating your own URLClassloader with your plugin classloader as the parent. I understand that this may be viewed as a breaking change to Bukkit, but we cannot support random usage of reflection or assumptions that aren’t codified in the API. |