Migrated attachment for Guice issue 288, comment 28
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 1479) | |
+++ 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 1479) | |
+++ 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,34 @@ | |
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 Class<?> EXECUTOR_CLASS; | |
+ | |
+ static { | |
+ Class<?> executorClass = null; | |
+ try { | |
+ String executorName = System.getProperty("guice.executor.class"); | |
+ if (executorName == null) { | |
+ executorClass = SimpleExecutor.class; | |
+ } else if (executorName.length() > 0) { | |
+ executorClass = Finalizer.class.getClassLoader().loadClass(executorName); | |
+ } | |
+ } catch (Throwable t) { | |
+ logger.log(Level.WARNING, "Cannot load Executor class.", t); | |
+ } | |
+ EXECUTOR_CLASS = executorClass; | |
+ } | |
+ | |
+ /* Simple Executor that just creates a new thread */ | |
+ static final class SimpleExecutor implements Executor { | |
+ public void execute(Runnable command) { | |
+ Thread thread = new Thread(command, command.getClass().getName()); | |
+ thread.setDaemon(true); | |
+ // TODO: Priority? | |
+ thread.start(); | |
+ } | |
+ } | |
+ | |
/** | |
* Starts the Finalizer thread. FinalizableReferenceQueue calls this method | |
* reflectively. | |
@@ -79,8 +108,17 @@ | |
} | |
Finalizer finalizer = new Finalizer(finalizableReferenceClass, frq); | |
- finalizer.start(); | |
- return finalizer.queue; | |
+ | |
+ if (null != EXECUTOR_CLASS) { | |
+ try { | |
+ ((Executor)EXECUTOR_CLASS.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,17 +127,12 @@ | |
/** 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? | |
} | |
/** | |
Index: core/src/com/google/inject/internal/BytecodeGen.java | |
=================================================================== | |
--- core/src/com/google/inject/internal/BytecodeGen.java (revision 1479) | |
+++ 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