diff options
Diffstat (limited to 'patches/api/0204-Prioritise-own-classes-where-possible.patch')
-rw-r--r-- | patches/api/0204-Prioritise-own-classes-where-possible.patch | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/patches/api/0204-Prioritise-own-classes-where-possible.patch b/patches/api/0204-Prioritise-own-classes-where-possible.patch new file mode 100644 index 0000000000..948e2f95fa --- /dev/null +++ b/patches/api/0204-Prioritise-own-classes-where-possible.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm <[email protected]> +Date: Mon, 27 Apr 2020 12:31:59 +0200 +Subject: [PATCH] Prioritise own classes where possible + +This adds the server property `Paper.DisableClassPrioritization` to disable +prioritization of own classes for plugins' classloaders. + +This value is by default not present, and this will therefore break any +plugins which abuse behaviour related to not using their own classes +while still loading their own. This is often an issue with failing to +relocate or shade properly, such as when shading plugin APIs like Vault. + +A plugin's classloader will first look in the same jar as it is loading +in for a requested class, then load it. It does not re-use other +plugins' classes if it has the chance to avoid doing so. + +If a class is not found in the same jar as it is loading for and it does +find it elsewhere, it will still choose the class elsewhere. This is +intended behaviour, as it will only prioritise classes it has in its own +jar, no other plugins' classes will be prioritised in any other order +than the one they were registered in. + +The patch in general terms just loads the class in the plugin's jar +before it starts looking elsewhere for it. + +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index cf809eda2a3feb6abccf7286068280f430452135..4b54af83ef8fd18696d2d21ed52b61f13bff7988 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -51,6 +51,7 @@ import org.yaml.snakeyaml.error.YAMLException; + */ + public final class JavaPluginLoader implements PluginLoader { + final Server server; ++ private static final boolean DISABLE_CLASS_PRIORITIZATION = Boolean.getBoolean("Paper.DisableClassPrioritization"); // Paper + private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; + private final Map<String, java.util.concurrent.locks.ReentrantReadWriteLock> classLoadLock = new java.util.HashMap<String, java.util.concurrent.locks.ReentrantReadWriteLock>(); // Paper + private final Map<String, Integer> classLoadLockCount = new java.util.HashMap<String, Integer>(); // Paper +@@ -203,6 +204,11 @@ public final class JavaPluginLoader implements PluginLoader { + + @Nullable + Class<?> getClassByName(final String name, boolean resolve, PluginDescriptionFile description) { ++ // Paper start - prioritize self ++ return getClassByName(name, resolve, description, null); ++ } ++ Class<?> getClassByName(final String name, boolean resolve, PluginDescriptionFile description, PluginClassLoader requester) { ++ // Paper end + // Paper start - make MT safe + java.util.concurrent.locks.ReentrantReadWriteLock lock; + synchronized (classLoadLock) { +@@ -210,6 +216,13 @@ public final class JavaPluginLoader implements PluginLoader { + classLoadLockCount.compute(name, (x, prev) -> prev != null ? prev + 1 : 1); + } + lock.writeLock().lock();try { ++ // Paper start - prioritize self ++ if (!DISABLE_CLASS_PRIORITIZATION && requester != null) { ++ try { ++ return requester.loadClass0(name, false, false, ((SimplePluginManager) server.getPluginManager()).isTransitiveDepend(description, requester.getDescription())); ++ } catch (ClassNotFoundException cnfe) {} ++ } ++ // Paper end + // Paper end + for (PluginClassLoader loader : loaders) { + try { +diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +index 0db641f5d5e1293b236ad0d2e3a156802ffed839..064c758b19bc8c9a4e94769dd205a1bdcc972a89 100644 +--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +@@ -33,7 +33,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + public JavaPlugin getPlugin() { return plugin; } // Spigot + private final JavaPluginLoader loader; + private final Map<String, Class<?>> classes = new ConcurrentHashMap<String, Class<?>>(); +- private final PluginDescriptionFile description; ++ private final PluginDescriptionFile description; PluginDescriptionFile getDescription() { return description; } // Paper + private final File dataFolder; + private final File file; + private final JarFile jar; +@@ -123,7 +123,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + + if (checkGlobal) { + // This ignores the libraries of other plugins, unless they are transitive dependencies. +- Class<?> result = loader.getClassByName(name, resolve, description); ++ Class<?> result = loader.getClassByName(name, resolve, description, this); // Paper - prioritize self + + if (result != null) { + // If the class was loaded from a library instead of a PluginClassLoader, we can assume that its associated plugin is a transitive dependency and can therefore skip this check. |