Created
July 7, 2014 18:10
-
-
Save gissuebot/684a9d0e8123146ce400 to your computer and use it in GitHub Desktop.
Migrated attachment for Guice issue 288, comment 39
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: core/src/com/google/inject/internal/util/FinalizableReferenceQueue.java | |
=================================================================== | |
--- core/src/com/google/inject/internal/util/FinalizableReferenceQueue.java (revision 1482) | |
+++ core/src/com/google/inject/internal/util/FinalizableReferenceQueue.java (working copy) | |
@@ -118,24 +118,27 @@ | |
@SuppressWarnings("unchecked") | |
public FinalizableReferenceQueue() { | |
// We could start the finalizer lazily, but I'd rather it blow up early. | |
- ReferenceQueue<Object> queue; | |
- boolean threadStarted = false; | |
+ ReferenceQueue<Object> queue = null; | |
try { | |
queue = (ReferenceQueue<Object>) startFinalizer.invoke(null, | |
FinalizableReference.class, this); | |
- threadStarted = true; | |
} catch (IllegalAccessException e) { | |
// Finalizer.startFinalizer() is public. | |
throw new AssertionError(e); | |
} catch (Throwable t) { | |
- logger.log(Level.INFO, "Failed to start reference finalizer thread." | |
+ logger.log(Level.WARNING, "Exception in startFinalizer method.", t); | |
+ } | |
+ | |
+ if (queue == null) { | |
+ logger.log(Level.INFO, "Reference Finalizer thread is not available." | |
+ " Reference cleanup will only occur when new references are" | |
- + " created.", t); | |
- queue = new ReferenceQueue<Object>(); | |
+ + " created."); | |
+ this.queue = new ReferenceQueue<Object>(); | |
+ this.threadStarted = false; | |
+ } else { | |
+ this.queue = queue; | |
+ this.threadStarted = true; | |
} | |
- | |
- this.queue = queue; | |
- this.threadStarted = threadStarted; | |
} | |
/** | |
Index: core/src/com/google/inject/internal/util/Finalizer.java | |
=================================================================== | |
--- core/src/com/google/inject/internal/util/Finalizer.java (revision 1482) | |
+++ core/src/com/google/inject/internal/util/Finalizer.java (working copy) | |
@@ -21,6 +21,7 @@ | |
import java.lang.ref.ReferenceQueue; | |
import java.lang.ref.WeakReference; | |
import java.lang.reflect.Method; | |
+import java.util.concurrent.Executor; | |
import java.util.logging.Level; | |
import java.util.logging.Logger; | |
@@ -45,7 +46,7 @@ | |
* class loader from getting garbage collected, and this class can detect when | |
* the main class loader has been garbage collected and stop itself. | |
*/ | |
-public class Finalizer extends Thread { | |
+public class Finalizer implements Runnable { | |
private static final Logger logger | |
= Logger.getLogger(Finalizer.class.getName()); | |
@@ -54,6 +55,17 @@ | |
private static final String FINALIZABLE_REFERENCE | |
= "com.google.inject.internal.util.FinalizableReference"; | |
+ /** Use "-Dguice.executor.class=Clazz" where Clazz implements java.util.concurrent.Executor. */ | |
+ private static final String EXECUTOR_CLASS_NAME; | |
+ | |
+ static { | |
+ String executorClassName = null; | |
+ try { | |
+ executorClassName = System.getProperty("guice.executor.class"); | |
+ } catch (Throwable t) {} | |
+ EXECUTOR_CLASS_NAME = executorClassName; | |
+ } | |
+ | |
/** | |
* Starts the Finalizer thread. FinalizableReferenceQueue calls this method | |
* reflectively. | |
@@ -78,9 +90,33 @@ | |
"Expected " + FINALIZABLE_REFERENCE + "."); | |
} | |
+ if ("NONE".equalsIgnoreCase(EXECUTOR_CLASS_NAME)) { | |
+ return null; | |
+ } | |
+ | |
Finalizer finalizer = new Finalizer(finalizableReferenceClass, frq); | |
- finalizer.start(); | |
- return finalizer.queue; | |
+ | |
+ try { | |
+ if (EXECUTOR_CLASS_NAME == null || EXECUTOR_CLASS_NAME.length() == 0) { | |
+ Thread thread = new Thread(finalizer, Finalizer.class.getName()); | |
+ thread.setDaemon(true); | |
+ // TODO: Priority? | |
+ thread.start(); | |
+ } else { | |
+ Class<?> executorClass; | |
+ try { | |
+ executorClass = Thread.currentThread().getContextClassLoader().loadClass(EXECUTOR_CLASS_NAME); | |
+ } catch (Throwable ignore) { | |
+ executorClass = Class.forName(EXECUTOR_CLASS_NAME); | |
+ } | |
+ // use custom Executor supplied by an external container | |
+ ((Executor)executorClass.newInstance()).execute(finalizer); | |
+ } | |
+ return finalizer.queue; | |
+ } catch (Throwable t) { | |
+ logger.log(Level.WARNING, "Cannot start Finalizer thread.", t); | |
+ return null; | |
+ } | |
} | |
private final WeakReference<Class<?>> finalizableReferenceClassReference; | |
@@ -89,24 +125,18 @@ | |
/** Constructs a new finalizer thread. */ | |
private Finalizer(Class<?> finalizableReferenceClass, Object frq) { | |
- super(Finalizer.class.getName()); | |
this.finalizableReferenceClassReference | |
= new WeakReference<Class<?>>(finalizableReferenceClass); | |
// Keep track of the FRQ that started us so we know when to stop. | |
this.frqReference = new PhantomReference<Object>(frq, queue); | |
- | |
- setDaemon(true); | |
- | |
- // TODO: Priority? | |
} | |
/** | |
* Loops continuously, pulling references off the queue and cleaning them up. | |
*/ | |
@SuppressWarnings("InfiniteLoopStatement") | |
- @Override | |
public void run() { | |
try { | |
while (true) { | |
Index: core/src/com/google/inject/internal/BytecodeGen.java | |
=================================================================== | |
--- core/src/com/google/inject/internal/BytecodeGen.java (revision 1482) | |
+++ core/src/com/google/inject/internal/BytecodeGen.java (working copy) | |
@@ -119,8 +119,7 @@ | |
end[NO_AOP]*/ | |
/** Use "-Dguice.custom.loader=false" to disable custom classloading. */ | |
- private static final boolean CUSTOM_LOADER_ENABLED | |
- = Boolean.parseBoolean(System.getProperty("guice.custom.loader", "true")); | |
+ private static final boolean CUSTOM_LOADER_ENABLED; | |
/** | |
* Weak cache of bridge class loaders that make the Guice implementation | |
@@ -129,6 +128,14 @@ | |
private static final Map<ClassLoader, ClassLoader> CLASS_LOADER_CACHE; | |
static { | |
+ boolean customLoaderEnabled; | |
+ try { | |
+ customLoaderEnabled = Boolean.parseBoolean(System.getProperty("guice.custom.loader", "true")); | |
+ } catch (Throwable e) { | |
+ customLoaderEnabled = false; // unlikely we'll also have permissions for custom loading | |
+ } | |
+ CUSTOM_LOADER_ENABLED = customLoaderEnabled; | |
+ | |
if (CUSTOM_LOADER_ENABLED) { | |
CLASS_LOADER_CACHE = new MapMaker().weakKeys().weakValues().makeComputingMap( | |
new Function<ClassLoader, ClassLoader>() { |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment