aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/api/0204-Prioritise-own-classes-where-possible.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/api/0204-Prioritise-own-classes-where-possible.patch')
-rw-r--r--patches/api/0204-Prioritise-own-classes-where-possible.patch86
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.