diff --git a/ItemDisguise/.classpath b/ItemDisguise/.classpath
index 2bda6dc7..71e70473 100644
--- a/ItemDisguise/.classpath
+++ b/ItemDisguise/.classpath
@@ -7,12 +7,6 @@
-
-
-
-
-
-
diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/BackgroundCompiler.java b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/BackgroundCompiler.java
index 4359e080..836a45d1 100644
--- a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/BackgroundCompiler.java
+++ b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/BackgroundCompiler.java
@@ -17,6 +17,10 @@
package com.comphenix.protocol.reflect.compiler;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryPoolMXBean;
+import java.lang.management.MemoryUsage;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
@@ -29,6 +33,9 @@ import javax.annotation.Nullable;
import com.comphenix.protocol.error.ErrorReporter;
import com.comphenix.protocol.reflect.StructureModifier;
+import com.comphenix.protocol.reflect.compiler.StructureCompiler.StructureKey;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
/**
@@ -48,15 +55,26 @@ public class BackgroundCompiler {
// How long to wait for a shutdown
public static final int SHUTDOWN_DELAY_MS = 2000;
+ /**
+ * The default fraction of perm gen space after which the background compiler will be disabled.
+ */
+ public static final double DEFAULT_DISABLE_AT_PERM_GEN = 0.65;
+
// The single background compiler we're using
private static BackgroundCompiler backgroundCompiler;
+ // Classes we're currently compiling
+ private Map>> listeners = Maps.newHashMap();
+ private Object listenerLock = new Object();
+
private StructureCompiler compiler;
private boolean enabled;
private boolean shuttingDown;
private ExecutorService executor;
private ErrorReporter reporter;
+
+ private double disablePermGenFraction = DEFAULT_DISABLE_AT_PERM_GEN;
/**
* Retrieves the current background compiler.
@@ -139,26 +157,61 @@ public class BackgroundCompiler {
* @param uncompiled - structure modifier to compile.
* @param listener - listener responsible for responding to the compilation.
*/
+ @SuppressWarnings({"rawtypes", "unchecked"})
public void scheduleCompilation(final StructureModifier uncompiled, final CompileListener listener) {
-
// Only schedule if we're enabled
if (enabled && !shuttingDown) {
+ // Check perm gen
+ if (getPermGenUsage() > disablePermGenFraction)
+ return;
// Don't try to schedule anything
if (executor == null || executor.isShutdown())
return;
+
+ // Use to look up structure modifiers
+ final StructureKey key = new StructureKey(uncompiled);
+
+ // Allow others to listen in too
+ synchronized (listenerLock) {
+ List list = listeners.get(key);
+
+ if (!listeners.containsKey(key)) {
+ listeners.put(key, (List) Lists.newArrayList(listener));
+ } else {
+ // We're currently compiling
+ list.add(listener);
+ return;
+ }
+ }
// Create the worker that will compile our modifier
Callable> worker = new Callable