PaperMC / Velocity

The modern, next-generation Minecraft server proxy.
https://papermc.io/software/velocity
GNU General Public License v3.0
1.78k stars 625 forks source link

Jigsaw Modules Support #354

Open A248 opened 4 years ago

A248 commented 4 years ago

At the moment, Velocity does not have any support for JPMS modules. This is expected, since it's a Java-8 compatible project loading plugins using URLClassLoader.

For plugins targeting Java 11, it is quite an improvement to take advantage of Java 11. However, PluginClassLoader loads every plugin as an unnamed module. This is the case even for jars with a manifest declaring Automatic-Module-Name, as well as plugin jars with a full module-info.java. Therefore, plugin loading makes it impossible to load own's plugin classes as anything other than an unnamed module.

The Annotation Processor Additionally, adding a module-info.java causes the annotation processor to stop creating velocity-plugin.json. I am not entirely sure why this is. At first, I believed it due to an accidental omission of "exports testpluginpackage", but neither adding this export declaration nor adding an opens declaration solved the issue. It is still possible to manually copy a velocity-plugin.json into a jar with module-info, but as noted, no named module is created.

Velocity's Module Name Ideally, Velocity would have an Automatic-Module-Name so that modular plugins may use a full module-info without depending on file name-based module names.

Using ModuleLayer in Plugins Although it is possible for a plugin to create one's own ModuleLayer, and load jars, including named modules, into it, this approach is by little means useful. Without significant difficulty and access to Velocity internals, classes in the module layer will not be visible to other plugins, which prevents using modules anywhere but internally, defeating most of its advantages.

Summary There are a few things which would need to be done for full modules support:

astei commented 4 years ago

I will probably consider this if and when we bump Velocity to Java 11 as the minimum.

astei commented 4 years ago

We are going to be using Java 11 as the minimum in Velocity 2.0.0 so the path is clear to implement this.

orblazer commented 2 years ago

Hello, I have start on an proof of concept for that issue. I have make an repo with implementation of plugin system like this project and load plugins with ModuleLayer. The repo is accessible here https://github.com/orblazer/velocity-jpms

Currently i have 1 big issue, its how i can run the app in modules mode (idealy) because the plugins need to have api and probably app (proxy in velocity) for allow plugin to use thats modules.

A248 commented 2 years ago

@orblazer I suggest creating a jar with nested jars, then extracting them at runtime.

I've previous work implementing this in a server fork for someone else. If you want an operative Velocity server with module support, let me know.

In my experience, the greatest gain from using the module system is its ability to screen plugins for unrelocated dependencies. That, and fine-tuned control over plugins' access to internal APIs by hacks such as setAccessible. It is very illuminating to see which of a server's plugins reach deep into the implementation, and for what reasons.

orblazer commented 2 years ago

@A248 im open to see how you have done this, but yeah the nested jars is look like good idea.

I think for plugins we need find an existing plugin or creating one for gradle for generate that jar.

Another think we can do but that involve more work, we can create an custom ClassLoader for each plugin and isolate the classpath. I think that way could be great because the JPMS add a lot of more complexe things for implement that thinks without lot of work for plugin developers but that also add a lot of benefit like dependency management and service system.

orblazer commented 1 year ago

Hello @A248 (or other), you have any advice on this ? I'm curious to more dig this.

Thanks.

A248 commented 1 year ago

I don't think JPMS is complicated. It is the standard module system implemented for the Java platform, and it is very suitable to a plugin environment. If it came to Velocity, it would be very welcome.

Adding module layers to Velocity's plugin-loading is achievable once you are moderately acquainted with the ModuleLayer API. Some refactoring is necessary, but nothing insurmountable. I can write up a draft PR if you'd like to see, but there's no rush; I'll explain.

Plugins wouldn't be strictly required to adopt the module system. Writing module-info has never been a requirement. However, there is much to be gained for well-behaved, properly-namespaced plugins in terms of the lucidity and reliability of inter-plugin dependencies. Some plugins might have to resolve a few matters before becoming full modules. In the meantime, they may still declare automatic module names so that other plugins may depend on them.

The only challenge for Velocity to implement the module system is the API method PluginManager#addToClasspath. This will have to go. There is no way to append to an existing module path using JPMS. All jars must be resolved eagerly. So, I imagine that fully adding JPMS to Velocity will require Velocity Polymer. Hence this issue is tacked onto the Velocity Polymer milestone.