87 Zeilen
5.2 KiB
Diff
87 Zeilen
5.2 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Mariell Hoversholm <proximyst@proximyst.com>
|
|
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 ce751577623eaad0f31e2eb7bf0842d1ab73e845..31793f46e5623729dfb4048e901f274082f57826 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 b9766b9b47547c400ed075f1635bb1461cb5e860..87016d01640d8ea86b93cf2f7ead4c88b6d9d778 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;
|
|
@@ -118,7 +118,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 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.
|
|
if (result != null && result.getClassLoader() instanceof PluginClassLoader) {
|