Fix extension loading causing whole plugin to error

This commit is contained in:
Luck 2021-06-13 12:46:02 +01:00
parent 51202924af
commit 4598435dd4
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
2 changed files with 25 additions and 13 deletions

View File

@ -28,6 +28,7 @@ package me.lucko.luckperms.common.extension;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.plugin.classpath.ReflectionClassPathAppender;
import me.lucko.luckperms.common.util.gson.GsonProvider; import me.lucko.luckperms.common.util.gson.GsonProvider;
import net.luckperms.api.LuckPerms; import net.luckperms.api.LuckPerms;
@ -42,8 +43,6 @@ import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
@ -98,7 +97,7 @@ public class SimpleExtensionManager implements ExtensionManager, AutoCloseable {
if (path.getFileName().toString().endsWith(".jar")) { if (path.getFileName().toString().endsWith(".jar")) {
try { try {
loadExtension(path); loadExtension(path);
} catch (IOException e) { } catch (Exception e) {
this.plugin.getLogger().warn("Exception loading extension from " + path, e); this.plugin.getLogger().warn("Exception loading extension from " + path, e);
} }
} }
@ -146,7 +145,7 @@ public class SimpleExtensionManager implements ExtensionManager, AutoCloseable {
if (useParentClassLoader && isJarInJar()) { if (useParentClassLoader && isJarInJar()) {
try { try {
addJarToParentClasspath(path); addJarToParentClasspath(path);
} catch (Exception e) { } catch (Throwable e) {
throw new RuntimeException("Exception whilst classloading extension", e); throw new RuntimeException("Exception whilst classloading extension", e);
} }
} else { } else {
@ -200,16 +199,14 @@ public class SimpleExtensionManager implements ExtensionManager, AutoCloseable {
return thisClassLoaderName.equals("me.lucko.luckperms.common.loader.JarInJarClassLoader"); return thisClassLoaderName.equals("me.lucko.luckperms.common.loader.JarInJarClassLoader");
} }
@Deprecated
private static void addJarToParentClasspath(Path path) throws Exception { private static void addJarToParentClasspath(Path path) throws Exception {
ClassLoader parentClassLoader = SimpleExtensionManager.class.getClassLoader().getParent(); ClassLoader parentClassLoader = SimpleExtensionManager.class.getClassLoader().getParent();
if (!(parentClassLoader instanceof URLClassLoader)) { if (!(parentClassLoader instanceof URLClassLoader)) {
throw new RuntimeException("useParentClassLoader is true but parent is not a URLClassLoader"); throw new RuntimeException("useParentClassLoader is true but parent is not a URLClassLoader");
} }
Method addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); ReflectionClassPathAppender.addUrl(((URLClassLoader) parentClassLoader), path.toUri().toURL());
addUrlMethod.setAccessible(true);
addUrlMethod.invoke(parentClassLoader, path.toUri().toURL());
} }
private static final class LoadedExtension { private static final class LoadedExtension {

View File

@ -43,16 +43,32 @@ public class ReflectionClassPathAppender implements ClassPathAppender {
try { try {
openUrlClassLoaderModule(); openUrlClassLoaderModule();
} catch (Throwable e) { } catch (Throwable e) {
// ignore exception - will throw on Java 8 since the Module classes don't exist // ignore
} }
// Get the protected 'addURL' method on URLClassLoader and set it to accessible.
try { try {
ADD_URL_METHOD = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); ADD_URL_METHOD = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
ADD_URL_METHOD.setAccessible(true);
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
try {
ADD_URL_METHOD.setAccessible(true);
} catch (Throwable e) {
new RuntimeException("LuckPerms is unable to access the URLClassLoader#addURL method using reflection. \n" +
"You may be able to fix this problem by adding the following command-line argument " +
"directly after the 'java' command in your start script: \n'--add-opens java.base/java.lang=ALL-UNNAMED'", e).printStackTrace();
}
}
/**
* Adds the given {@link URL} to the class loader.
*
* @param classLoader the class loader
* @param url the url to add
*/
public static void addUrl(URLClassLoader classLoader, URL url) throws ReflectiveOperationException {
ADD_URL_METHOD.invoke(classLoader, url);
} }
private final URLClassLoader classLoader; private final URLClassLoader classLoader;
@ -69,13 +85,12 @@ public class ReflectionClassPathAppender implements ClassPathAppender {
@Override @Override
public void addJarToClasspath(Path file) { public void addJarToClasspath(Path file) {
try { try {
ADD_URL_METHOD.invoke(this.classLoader, file.toUri().toURL()); addUrl(this.classLoader, file.toUri().toURL());
} catch (ReflectiveOperationException | MalformedURLException e) { } catch (ReflectiveOperationException | MalformedURLException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
@SuppressWarnings("JavaReflectionMemberAccess")
private static void openUrlClassLoaderModule() throws Exception { private static void openUrlClassLoaderModule() throws Exception {
// This is effectively calling: // This is effectively calling:
// //