mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-30 22:53:27 +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;
|
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 me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
@ -38,10 +35,28 @@ import java.net.URLClassLoader;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
public class ReflectionClassLoader implements PluginClassLoader {
|
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 static final Method ADD_URL_METHOD;
|
||||||
private final Supplier<Method> addUrlMethod;
|
|
||||||
|
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 {
|
public ReflectionClassLoader(LuckPermsBootstrap bootstrap) throws IllegalStateException {
|
||||||
ClassLoader classLoader = bootstrap.getClass().getClassLoader();
|
ClassLoader classLoader = bootstrap.getClass().getClassLoader();
|
||||||
@ -50,42 +65,35 @@ public class ReflectionClassLoader implements PluginClassLoader {
|
|||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("ClassLoader is not instance of URLClassLoader");
|
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
|
@Override
|
||||||
public void addJarToClasspath(Path file) {
|
public void addJarToClasspath(Path file) {
|
||||||
try {
|
try {
|
||||||
this.addUrlMethod.get().invoke(this.classLoader, file.toUri().toURL());
|
ADD_URL_METHOD.invoke(this.classLoader, file.toUri().toURL());
|
||||||
} catch (IllegalAccessException | InvocationTargetException | MalformedURLException e) {
|
} catch (IllegalAccessException | InvocationTargetException | MalformedURLException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("JavaReflectionMemberAccess")
|
@SuppressWarnings("JavaReflectionMemberAccess")
|
||||||
private static boolean isJava9OrNewer() {
|
private static void openUrlClassLoaderModule() throws Exception {
|
||||||
try {
|
// This is effectively calling:
|
||||||
// method was added in the Java 9 release
|
//
|
||||||
Runtime.class.getMethod("version");
|
// URLClassLoader.class.getModule().addOpens(
|
||||||
return true;
|
// URLClassLoader.class.getPackageName(),
|
||||||
} catch (NoSuchMethodException e) {
|
// ReflectionClassLoader.class.getModule()
|
||||||
return false;
|
// );
|
||||||
}
|
//
|
||||||
|
// 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