aboutsummaryrefslogtreecommitdiffhomepage
path: root/Spigot-API-Patches-Unmapped/0193-Make-JavaPluginLoader-thread-safe.patch
blob: 21dbe589a495f7b3b61faf1e3bec624fcd89d403 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
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
index de44d850d7b3ab3e528eb6f2de375a6c3e0e5cf9..9d1f7cdf12029c8198792fd299f92be476040222 100644
--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
@@ -52,6 +52,8 @@ public final class JavaPluginLoader implements PluginLoader {
     final Server server;
     private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")};
     private final Map<String, Class<?>> classes = new ConcurrentHashMap<String, Class<?>>();
+    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>();
 
     /**
@@ -191,7 +193,19 @@ public final class JavaPluginLoader implements PluginLoader {
 
     @Nullable
     Class<?> getClassByName(final String name) {
+        // Paper start - make MT safe
         Class<?> cachedClass = classes.get(name);
+        if (cachedClass != null) {
+            return cachedClass;
+        }
+        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 {
+        cachedClass = classes.get(name);
+        // Paper end
 
         if (cachedClass != null) {
             return cachedClass;
@@ -205,6 +219,19 @@ public final class JavaPluginLoader implements PluginLoader {
                 }
             }
         }
+        // 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;
     }