2020-05-06 09:48:49 +00:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2020-04-15 07:39:39 +00:00
From: Trigary <trigary0@gmail.com>
Date: Wed, 15 Apr 2020 01:24:55 -0400
Subject: [PATCH] Make JavaPluginLoader thread-safe
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
2021-05-15 21:10:57 +00:00
index de44d850d7b3ab3e528eb6f2de375a6c3e0e5cf9..9d1f7cdf12029c8198792fd299f92be476040222 100644
2020-04-15 07:39:39 +00:00
--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
2021-05-15 21:10:57 +00:00
@@ -52,6 +52,8 @@ public final class JavaPluginLoader implements PluginLoader {
2020-04-15 07:39:39 +00:00
final Server server;
private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")};
2021-05-15 21:10:57 +00:00
private final Map<String, Class<?>> classes = new ConcurrentHashMap<String, Class<?>>();
2020-04-15 07:39:39 +00:00
+ 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
private final List<PluginClassLoader> loaders = new CopyOnWriteArrayList<PluginClassLoader>();
2021-05-15 21:10:57 +00:00
/**
@@ -191,7 +193,19 @@ public final class JavaPluginLoader implements PluginLoader {
2020-04-15 07:39:39 +00:00
@Nullable
2021-05-15 21:10:57 +00:00
Class<?> getClassByName(final String name) {
2020-04-15 07:39:39 +00:00
+ // Paper start - make MT safe
2021-05-15 21:10:57 +00:00
Class<?> cachedClass = classes.get(name);
+ if (cachedClass != null) {
+ return cachedClass;
+ }
2020-04-15 07:39:39 +00:00
+ java.util.concurrent.locks.ReentrantReadWriteLock lock;
+ synchronized (classLoadLock) {
+ lock = classLoadLock.computeIfAbsent(name, (x) -> new java.util.concurrent.locks.ReentrantReadWriteLock());
+ classLoadLockCount.compute(name, (x, prev) -> prev != null ? prev + 1 : 1);
+ }
+ lock.writeLock().lock();try {
2021-05-15 21:10:57 +00:00
+ cachedClass = classes.get(name);
2020-04-15 07:39:39 +00:00
+ // Paper end
2021-05-15 21:10:57 +00:00
if (cachedClass != null) {
return cachedClass;
@@ -205,6 +219,19 @@ public final class JavaPluginLoader implements PluginLoader {
}
2020-04-15 07:39:39 +00:00
}
}
+ // Paper start - make MT safe
+ } finally {
+ synchronized (classLoadLock) {
+ lock.writeLock().unlock();
+ if (classLoadLockCount.get(name) == 1) {
+ classLoadLock.remove(name);
+ classLoadLockCount.remove(name);
+ } else {
+ classLoadLockCount.compute(name, (x, prev) -> prev - 1);
+ }
+ }
+ }
+ // Paper end
return null;
}