Correctly Remove Classloaders, Avoid Loading Providers in /paper dumpplugins, Fix library lookup (#8938)

This commit is contained in:
Owen 2023-03-06 19:20:11 -05:00 committed by GitHub
parent bf2053a156
commit 4d7269e07c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 119 additions and 63 deletions

View file

@ -258,10 +258,10 @@ index 0000000000000000000000000000000000000000..f0fce4113fb07c64adbec029d177c236
+}
diff --git a/src/main/java/io/papermc/paper/command/subcommands/DumpPluginsCommand.java b/src/main/java/io/papermc/paper/command/subcommands/DumpPluginsCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..4ecd00b32c7abc15d655dd3c999b6feca332c3a1
index 0000000000000000000000000000000000000000..7159c72408f556d676eded668057a4c5ebb21719
--- /dev/null
+++ b/src/main/java/io/papermc/paper/command/subcommands/DumpPluginsCommand.java
@@ -0,0 +1,187 @@
@@ -0,0 +1,200 @@
+package io.papermc.paper.command.subcommands;
+
+import com.google.gson.JsonArray;
@ -276,6 +276,8 @@ index 0000000000000000000000000000000000000000..4ecd00b32c7abc15d655dd3c999b6fec
+import io.papermc.paper.plugin.entrypoint.classloader.group.LockingClassLoaderGroup;
+import io.papermc.paper.plugin.entrypoint.classloader.group.PaperPluginClassLoaderStorage;
+import io.papermc.paper.plugin.entrypoint.classloader.group.SimpleListPluginClassLoaderGroup;
+import io.papermc.paper.plugin.entrypoint.classloader.group.SpigotPluginClassLoaderGroup;
+import io.papermc.paper.plugin.entrypoint.classloader.group.StaticPluginClassLoaderGroup;
+import io.papermc.paper.plugin.provider.entrypoint.DependencyContext;
+import io.papermc.paper.plugin.entrypoint.strategy.ModernPluginLoadingStrategy;
+import io.papermc.paper.plugin.entrypoint.strategy.ProviderConfiguration;
@ -390,10 +392,15 @@ index 0000000000000000000000000000000000000000..4ecd00b32c7abc15d655dd3c999b6fec
+
+ @Override
+ public boolean load(PluginProvider<Object> provider, Object provided) {
+ return true;
+ }
+
+ @Override
+ public boolean preloadProvider(PluginProvider<Object> provider) {
+ // Don't load provider
+ loadOrder.add(provider.getMeta().getName());
+ return false;
+ }
+
+ });
+ modernPluginLoadingStrategy.loadProviders(pluginProviders);
+
@ -430,6 +437,12 @@ index 0000000000000000000000000000000000000000..4ecd00b32c7abc15d655dd3c999b6fec
+ if (group instanceof SimpleListPluginClassLoaderGroup listGroup) {
+ JsonArray array = new JsonArray();
+ classLoadersRoot.addProperty("main", listGroup.toString());
+ if (group instanceof StaticPluginClassLoaderGroup staticPluginClassLoaderGroup) {
+ classLoadersRoot.addProperty("plugin-holder", staticPluginClassLoaderGroup.getPluginClassloader().toString());
+ } else if (group instanceof SpigotPluginClassLoaderGroup spigotPluginClassLoaderGroup) {
+ classLoadersRoot.addProperty("plugin-holder", spigotPluginClassLoaderGroup.getPluginClassLoader().toString());
+ }
+
+ classLoadersRoot.add("children", array);
+ for (ConfiguredPluginClassLoader innerGroup : listGroup.getClassLoaders()) {
+ array.add(this.writeClassloader(innerGroup));
@ -803,10 +816,10 @@ index 0000000000000000000000000000000000000000..f9a2c55a354c877749db3f92956de802
+}
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperPluginClassLoader.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperPluginClassLoader.java
new file mode 100644
index 0000000000000000000000000000000000000000..79581d917e754998123b94b9f4ea7d1e78f017ae
index 0000000000000000000000000000000000000000..ecd11d3bd6c7e80a9b33cb8c2d7ed8a582857533
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperPluginClassLoader.java
@@ -0,0 +1,202 @@
@@ -0,0 +1,207 @@
+package io.papermc.paper.plugin.entrypoint.classloader;
+
+import io.papermc.paper.plugin.configuration.PluginMeta;
@ -1008,6 +1021,11 @@ index 0000000000000000000000000000000000000000..79581d917e754998123b94b9f4ea7d1e
+ super.close();
+ }
+ }
+
+ @Override
+ public @Nullable PluginClassLoaderGroup getGroup() {
+ return this.group;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperSimplePluginClassLoader.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperSimplePluginClassLoader.java
new file mode 100644
@ -1186,7 +1204,7 @@ index 0000000000000000000000000000000000000000..eaf5c794cbe8d6138c9d60eaae20f5fc
+}
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/GlobalPluginClassLoaderGroup.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/GlobalPluginClassLoaderGroup.java
new file mode 100644
index 0000000000000000000000000000000000000000..2b7eef787f83e5a32896cb30c215406b6f652786
index 0000000000000000000000000000000000000000..2a4933088928a51c8135a3a60b7447d9d10c66c4
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/GlobalPluginClassLoaderGroup.java
@@ -0,0 +1,18 @@
@ -1205,7 +1223,7 @@ index 0000000000000000000000000000000000000000..2b7eef787f83e5a32896cb30c215406b
+
+ @Override
+ public String toString() {
+ return super.toString();
+ return "GLOBAL:" + super.toString();
+ }
+}
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/LockingClassLoaderGroup.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/LockingClassLoaderGroup.java
@ -1292,7 +1310,7 @@ index 0000000000000000000000000000000000000000..aae50ebba6ba1579b75af5370c8b020d
+}
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/PaperPluginClassLoaderStorage.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/PaperPluginClassLoaderStorage.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c906e2c7d972b221a41acd614e00d0fbc1227c6
index 0000000000000000000000000000000000000000..e6fcdeb96356ff4713627b1458ac8bbfad1866b1
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/PaperPluginClassLoaderStorage.java
@@ -0,0 +1,93 @@
@ -1302,7 +1320,6 @@ index 0000000000000000000000000000000000000000..2c906e2c7d972b221a41acd614e00d0f
+import io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader;
+import io.papermc.paper.plugin.provider.classloader.PaperClassLoaderStorage;
+import io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup;
+import org.bukkit.Bukkit;
+import org.bukkit.plugin.java.PluginClassLoader;
+import org.jetbrains.annotations.ApiStatus;
+
@ -1325,8 +1342,8 @@ index 0000000000000000000000000000000000000000..2c906e2c7d972b221a41acd614e00d0f
+ @Override
+ public PluginClassLoaderGroup registerSpigotGroup(PluginClassLoader pluginClassLoader) {
+ return this.registerGroup(pluginClassLoader, new SpigotPluginClassLoaderGroup(this.globalGroup, (library) -> {
+ return Bukkit.getServer().getPluginManager().isTransitiveDependency(pluginClassLoader.getConfiguration(), library.getConfiguration());
+ }));
+ return pluginClassLoader.dependencyContext.isTransitiveDependency(pluginClassLoader.getConfiguration(), library.getConfiguration());
+ }, pluginClassLoader));
+ }
+
+ @Override
@ -1343,7 +1360,7 @@ index 0000000000000000000000000000000000000000..2c906e2c7d972b221a41acd614e00d0f
+ }
+ }
+
+ return this.registerGroup(classLoader, new StaticPluginClassLoaderGroup(allowedLoaders, access));
+ return this.registerGroup(classLoader, new StaticPluginClassLoaderGroup(allowedLoaders, access, classLoader));
+ }
+
+ private PluginClassLoaderGroup registerGroup(ConfiguredPluginClassLoader classLoader, PluginClassLoaderGroup group) {
@ -1362,6 +1379,7 @@ index 0000000000000000000000000000000000000000..2c906e2c7d972b221a41acd614e00d0f
+ @Override
+ public void unregisterClassloader(ConfiguredPluginClassLoader configuredPluginClassLoader) {
+ this.globalGroup.remove(configuredPluginClassLoader);
+ this.groups.remove(configuredPluginClassLoader.getGroup());
+ for (PluginClassLoaderGroup group : this.groups) {
+ group.remove(configuredPluginClassLoader);
+ }
@ -1372,7 +1390,7 @@ index 0000000000000000000000000000000000000000..2c906e2c7d972b221a41acd614e00d0f
+ if (this.globalGroup.getClassLoaders().contains(pluginLoader)) {
+ return false;
+ } else {
+ this.globalGroup.getClassLoaders().add(pluginLoader);
+ this.globalGroup.add(pluginLoader);
+ return true;
+ }
+ }
@ -1532,14 +1550,15 @@ index 0000000000000000000000000000000000000000..3b670bd6b35ae7f56488a9b50df54709
+}
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/SpigotPluginClassLoaderGroup.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/SpigotPluginClassLoaderGroup.java
new file mode 100644
index 0000000000000000000000000000000000000000..5d26367524389388be163ae3120c1d2bf55cfef7
index 0000000000000000000000000000000000000000..5a9f5b18e24a89dd642149a7a3d49390328b864b
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/SpigotPluginClassLoaderGroup.java
@@ -0,0 +1,49 @@
@@ -0,0 +1,58 @@
+package io.papermc.paper.plugin.entrypoint.classloader.group;
+
+import io.papermc.paper.plugin.provider.classloader.ClassLoaderAccess;
+import io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader;
+import org.bukkit.plugin.java.PluginClassLoader;
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.function.Predicate;
@ -1552,10 +1571,12 @@ index 0000000000000000000000000000000000000000..5d26367524389388be163ae3120c1d2b
+public class SpigotPluginClassLoaderGroup extends SimpleListPluginClassLoaderGroup {
+
+ private final Predicate<ConfiguredPluginClassLoader> libraryClassloaderPredicate;
+ private final PluginClassLoader pluginClassLoader;
+
+ public SpigotPluginClassLoaderGroup(GlobalPluginClassLoaderGroup globalPluginClassLoaderGroup, Predicate<ConfiguredPluginClassLoader> libraryClassloaderPredicate) {
+ public SpigotPluginClassLoaderGroup(GlobalPluginClassLoaderGroup globalPluginClassLoaderGroup, Predicate<ConfiguredPluginClassLoader> libraryClassloaderPredicate, PluginClassLoader pluginClassLoader) {
+ super(globalPluginClassLoaderGroup.getClassLoaders());
+ this.libraryClassloaderPredicate = libraryClassloaderPredicate;
+ this.pluginClassLoader = pluginClassLoader;
+ }
+
+ // Mirrors global list
@ -1567,14 +1588,20 @@ index 0000000000000000000000000000000000000000..5d26367524389388be163ae3120c1d2b
+ public void remove(ConfiguredPluginClassLoader configuredPluginClassLoader) {
+ }
+
+ // Don't allow other plugins to access spigot dependencies, they should instead reference the global list
+ @Override
+ public ClassLoaderAccess getAccess() {
+ return v -> false;
+ }
+
+ @Override
+ protected Class<?> lookupClass(String name, boolean resolve, ConfiguredPluginClassLoader current) throws ClassNotFoundException {
+ return current.loadClass(name, resolve, false, this.libraryClassloaderPredicate.test(current));
+ }
+
+ @Override
+ public ClassLoaderAccess getAccess() {
+ return v -> true;
+ // DEBUG
+ public PluginClassLoader getPluginClassLoader() {
+ return pluginClassLoader;
+ }
+
+ @Override
@ -1587,10 +1614,10 @@ index 0000000000000000000000000000000000000000..5d26367524389388be163ae3120c1d2b
+}
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/StaticPluginClassLoaderGroup.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/StaticPluginClassLoaderGroup.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f7085b06271adf8a37485f4c9c9b8af605dd27d
index 0000000000000000000000000000000000000000..2412155ddfd559023f42ff534b8f06a52588e1e0
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/StaticPluginClassLoaderGroup.java
@@ -0,0 +1,31 @@
@@ -0,0 +1,40 @@
+package io.papermc.paper.plugin.entrypoint.classloader.group;
+
+import io.papermc.paper.plugin.provider.classloader.ClassLoaderAccess;
@ -1603,10 +1630,13 @@ index 0000000000000000000000000000000000000000..7f7085b06271adf8a37485f4c9c9b8af
+public class StaticPluginClassLoaderGroup extends SimpleListPluginClassLoaderGroup {
+
+ private final ClassLoaderAccess access;
+ // Debug only
+ private final ConfiguredPluginClassLoader mainClassloaderHolder;
+
+ public StaticPluginClassLoaderGroup(List<ConfiguredPluginClassLoader> classloaders, ClassLoaderAccess access) {
+ public StaticPluginClassLoaderGroup(List<ConfiguredPluginClassLoader> classloaders, ClassLoaderAccess access, ConfiguredPluginClassLoader mainClassloaderHolder) {
+ super(classloaders);
+ this.access = access;
+ this.mainClassloaderHolder = mainClassloaderHolder;
+ }
+
+ @Override
@ -1614,6 +1644,12 @@ index 0000000000000000000000000000000000000000..7f7085b06271adf8a37485f4c9c9b8af
+ return this.access;
+ }
+
+ // DEBUG
+ @ApiStatus.Internal
+ public ConfiguredPluginClassLoader getPluginClassloader() {
+ return this.mainClassloaderHolder;
+ }
+
+ @Override
+ public String toString() {
+ return "StaticPluginClassLoaderGroup{" +
@ -2404,10 +2440,10 @@ index 0000000000000000000000000000000000000000..779f6980a71db8df68c9cf2078497640
+}
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ModernPluginLoadingStrategy.java b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ModernPluginLoadingStrategy.java
new file mode 100644
index 0000000000000000000000000000000000000000..671e9ebb8246a4cc9e212f5b11ea476560f2f7d5
index 0000000000000000000000000000000000000000..1d58f3a438d5be423c84b2f61e496d938fdc2995
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ModernPluginLoadingStrategy.java
@@ -0,0 +1,209 @@
@@ -0,0 +1,211 @@
+package io.papermc.paper.plugin.entrypoint.strategy;
+
+import com.google.common.collect.Lists;
@ -2556,9 +2592,11 @@ index 0000000000000000000000000000000000000000..671e9ebb8246a4cc9e212f5b11ea4765
+ try {
+ this.configuration.applyContext(retrievedProvider, graphDependencyContext);
+
+ T instance = retrievedProvider.createInstance();
+ if (this.configuration.load(retrievedProvider, instance)) {
+ loadedPlugins.add(new ProviderPair<>(retrievedProvider, instance));
+ if (this.configuration.preloadProvider(retrievedProvider)) {
+ T instance = retrievedProvider.createInstance();
+ if (this.configuration.load(retrievedProvider, instance)) {
+ loadedPlugins.add(new ProviderPair<>(retrievedProvider, instance));
+ }
+ }
+ } catch (Throwable ex) {
+ LOGGER.error("Could not load plugin '%s' in folder '%s'".formatted(retrievedProvider.getFileName(), retrievedProvider.getParentSource()), ex); // Paper
@ -2644,17 +2682,15 @@ index 0000000000000000000000000000000000000000..2ea978ac957849260e7ca69c9ff56588
+}
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ProviderConfiguration.java b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ProviderConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..71536981075095ee06234c638c0dfa054e737fb8
index 0000000000000000000000000000000000000000..2c7a0751e5c8d0d1e42f7e245ba09815d4f6f8ff
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ProviderConfiguration.java
@@ -0,0 +1,19 @@
@@ -0,0 +1,21 @@
+package io.papermc.paper.plugin.entrypoint.strategy;
+
+import io.papermc.paper.plugin.provider.PluginProvider;
+import io.papermc.paper.plugin.provider.entrypoint.DependencyContext;
+
+import java.util.List;
+
+/**
+ * Used to share code with the modern and legacy plugin load strategy.
+ *
@ -2666,6 +2702,10 @@ index 0000000000000000000000000000000000000000..71536981075095ee06234c638c0dfa05
+
+ boolean load(PluginProvider<T> provider, T provided);
+
+ default boolean preloadProvider(PluginProvider<T> provider) {
+ return true;
+ }
+
+}
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ProviderLoadingStrategy.java b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ProviderLoadingStrategy.java
new file mode 100644
@ -4937,7 +4977,7 @@ index 0000000000000000000000000000000000000000..a180612a1ec395202dbae1ca5b97ec01
+}
diff --git a/src/main/java/io/papermc/paper/plugin/provider/source/DirectoryProviderSource.java b/src/main/java/io/papermc/paper/plugin/provider/source/DirectoryProviderSource.java
new file mode 100644
index 0000000000000000000000000000000000000000..1822e076601db51c8a7954036853bee1fb8e3704
index 0000000000000000000000000000000000000000..ed00c412f1703b38674bbd0d483fcb100aa99f9d
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/provider/source/DirectoryProviderSource.java
@@ -0,0 +1,40 @@
@ -4960,7 +5000,7 @@ index 0000000000000000000000000000000000000000..1822e076601db51c8a7954036853bee1
+ private static final Logger LOGGER = LogUtils.getLogger();
+
+ public DirectoryProviderSource() {
+ super("Directory '%s'"::formatted);
+ super("File '%s'"::formatted);
+ }
+
+ @Override
@ -5826,6 +5866,7 @@ index 0000000000000000000000000000000000000000..36f8dc31394333bb9aaa9341014037a4
+import com.destroystokyo.paper.util.SneakyThrow;
+import com.destroystokyo.paper.utils.PaperPluginLogger;
+import io.papermc.paper.plugin.entrypoint.dependency.DependencyUtil;
+import io.papermc.paper.plugin.manager.PaperPluginManagerImpl;
+import io.papermc.paper.plugin.provider.configuration.LoadOrderConfiguration;
+import io.papermc.paper.plugin.provider.entrypoint.DependencyContext;
+import io.papermc.paper.plugin.entrypoint.dependency.DependencyContextHolder;
@ -5942,7 +5983,7 @@ index 0000000000000000000000000000000000000000..36f8dc31394333bb9aaa9341014037a4
+
+ final PluginClassLoader loader;
+ try {
+ loader = new PluginClassLoader(this.getClass().getClassLoader(), this.description, dataFolder, this.path.toFile(), LIBRARY_LOADER.createLoader(this.description), this.jarFile); // Paper
+ loader = new PluginClassLoader(this.getClass().getClassLoader(), this.description, dataFolder, this.path.toFile(), LIBRARY_LOADER.createLoader(this.description), this.jarFile, this.dependencyContext); // Paper
+ } catch (InvalidPluginException ex) {
+ throw ex;
+ } catch (Throwable ex) {
@ -5951,8 +5992,7 @@ index 0000000000000000000000000000000000000000..36f8dc31394333bb9aaa9341014037a4
+
+ // Override dependency context.
+ // We must provide a temporary context in order to properly handle dependencies on the plugin classloader constructor.
+ // EDIT - Only re add if dependency checking is needed for spigot plugins, but not anymore.
+ // loader.dependencyContext = PaperPluginManagerImpl.getInstance();
+ loader.dependencyContext = PaperPluginManagerImpl.getInstance();
+
+
+ this.status = ProviderStatus.INITIALIZED;