Skip to content

Instantly share code, notes, and snippets.

@gissuebot
Created July 7, 2014 18:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gissuebot/130c92256db4c8703e97 to your computer and use it in GitHub Desktop.
Save gissuebot/130c92256db4c8703e97 to your computer and use it in GitHub Desktop.
Migrated attachment for Guice issue 288, comment 28
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