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/ebef93772bf6e03a710a to your computer and use it in GitHub Desktop.
Save gissuebot/ebef93772bf6e03a710a to your computer and use it in GitHub Desktop.
Migrated attachment for Guice issue 288, comment 30
Index: core/src/com/google/inject/internal/util/FinalizableReferenceQueue.java
===================================================================
--- core/src/com/google/inject/internal/util/FinalizableReferenceQueue.java (revision 1480)
+++ 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 1480)
+++ 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,28 @@
"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 {
+ // use custom Executor supplied by an external container
+ Class<?> executorClass = Finalizer.class.getClassLoader().loadClass(EXECUTOR_CLASS_NAME);
+ ((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 +120,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 1480)
+++ 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