mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-24 11:38:40 +01:00
Properly open URLClassLoader module on Java 9+ to allow reflection and avoid access warning (#952)
This commit is contained in:
parent
53fb46ee85
commit
8a38c5f4b7
@ -25,9 +25,6 @@
|
||||
|
||||
package me.lucko.luckperms.common.dependencies.classloader;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
|
||||
import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
@ -38,10 +35,28 @@ import java.net.URLClassLoader;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class ReflectionClassLoader implements PluginClassLoader {
|
||||
private final URLClassLoader classLoader;
|
||||
|
||||
@SuppressWarnings("Guava") // we can't use java.util.Function because old Guava versions are used at runtime
|
||||
private final Supplier<Method> addUrlMethod;
|
||||
private static final Method ADD_URL_METHOD;
|
||||
|
||||
static {
|
||||
// If on Java 9+, open the URLClassLoader module to this module
|
||||
// so we can access its API via reflection without producing a warning.
|
||||
try {
|
||||
openUrlClassLoaderModule();
|
||||
} catch (Throwable e) {
|
||||
// ignore exception - will throw on Java 8 since the Module classes don't exist
|
||||
}
|
||||
|
||||
// Get the protected 'addURL' method on URLClassLoader and set it to accessible.
|
||||
try {
|
||||
ADD_URL_METHOD = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
|
||||
ADD_URL_METHOD.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final URLClassLoader classLoader;
|
||||
|
||||
public ReflectionClassLoader(LuckPermsBootstrap bootstrap) throws IllegalStateException {
|
||||
ClassLoader classLoader = bootstrap.getClass().getClassLoader();
|
||||
@ -50,42 +65,35 @@ public class ReflectionClassLoader implements PluginClassLoader {
|
||||
} else {
|
||||
throw new IllegalStateException("ClassLoader is not instance of URLClassLoader");
|
||||
}
|
||||
|
||||
this.addUrlMethod = Suppliers.memoize(() -> {
|
||||
if (isJava9OrNewer()) {
|
||||
bootstrap.getPluginLogger().info("It is safe to ignore any warning printed following this message " +
|
||||
"starting with 'WARNING: An illegal reflective access operation has occurred, Illegal reflective " +
|
||||
"access by " + getClass().getName() + "'. This is intended, and will not have any impact on the " +
|
||||
"operation of LuckPerms.");
|
||||
}
|
||||
|
||||
try {
|
||||
Method addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
|
||||
addUrlMethod.setAccessible(true);
|
||||
return addUrlMethod;
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addJarToClasspath(Path file) {
|
||||
try {
|
||||
this.addUrlMethod.get().invoke(this.classLoader, file.toUri().toURL());
|
||||
ADD_URL_METHOD.invoke(this.classLoader, file.toUri().toURL());
|
||||
} catch (IllegalAccessException | InvocationTargetException | MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("JavaReflectionMemberAccess")
|
||||
private static boolean isJava9OrNewer() {
|
||||
try {
|
||||
// method was added in the Java 9 release
|
||||
Runtime.class.getMethod("version");
|
||||
return true;
|
||||
} catch (NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
private static void openUrlClassLoaderModule() throws Exception {
|
||||
// This is effectively calling:
|
||||
//
|
||||
// URLClassLoader.class.getModule().addOpens(
|
||||
// URLClassLoader.class.getPackageName(),
|
||||
// ReflectionClassLoader.class.getModule()
|
||||
// );
|
||||
//
|
||||
// We use reflection since we build against Java 8.
|
||||
|
||||
Class<?> moduleClass = Class.forName("java.lang.Module");
|
||||
Method getModuleMethod = Class.class.getMethod("getModule");
|
||||
Method addOpensMethod = moduleClass.getMethod("addOpens", String.class, moduleClass);
|
||||
|
||||
Object urlClassLoaderModule = getModuleMethod.invoke(URLClassLoader.class);
|
||||
Object thisModule = getModuleMethod.invoke(ReflectionClassLoader.class);
|
||||
|
||||
addOpensMethod.invoke(urlClassLoaderModule, URLClassLoader.class.getPackage().getName(), thisModule);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user