SF.net SVN: jython:[7112] trunk/jython
[email protected] Wed, 08 Sep 2010 06:27:14 +0000
| Newsgroups | gmane.comp.lang.jython.cvs |
|---|---|
| Message-ID | <[email protected]> |
Revision: 7112
http://jython.svn.sourceforge.net/jython/?rev=7112&view=rev
Author: zyasoft
Date: 2010-09-08 06:27:14 +0000 (Wed, 08 Sep 2010)
Log Message:
-----------
To address #1327 - removed use of Guava's FinalizableReferenceQueue
and now does a passive cleanup of PySystemState-related data, so that
classloaders will hopefully GC under a range of setups. Also
de-registers the shutdown hook.
Modified Paths:
--------------
trunk/jython/Lib/test/test_jy_internals.py
trunk/jython/Lib/test/test_weakref.py
trunk/jython/src/org/python/core/Py.java
trunk/jython/src/org/python/core/PySystemState.java
trunk/jython/src/org/python/util/PythonInterpreter.java
Modified: trunk/jython/Lib/test/test_jy_internals.py
===================================================================
--- trunk/jython/Lib/test/test_jy_internals.py 2010-09-07 20:49:59 UTC (rev 7111)
+++ trunk/jython/Lib/test/test_jy_internals.py 2010-09-08 06:27:14 UTC (rev 7112)
@@ -50,7 +50,6 @@
Dog().bark()
""")
- pi.cleanup();
make_clean()
# get to steady state first, then verify we don't create new proxies
Modified: trunk/jython/Lib/test/test_weakref.py
===================================================================
--- trunk/jython/Lib/test/test_weakref.py 2010-09-07 20:49:59 UTC (rev 7111)
+++ trunk/jython/Lib/test/test_weakref.py 2010-09-08 06:27:14 UTC (rev 7112)
@@ -12,8 +12,9 @@
def extra_collect():
"""Kick Java's GC into gear"""
gc.collect()
- time.sleep(0.1)
+ time.sleep(0.2)
gc.collect()
+ time.sleep(0.2)
gc.collect()
else:
def extra_collect():
Modified: trunk/jython/src/org/python/core/Py.java
===================================================================
--- trunk/jython/src/org/python/core/Py.java 2010-09-07 20:49:59 UTC (rev 7111)
+++ trunk/jython/src/org/python/core/Py.java 2010-09-08 06:27:14 UTC (rev 7112)
@@ -773,7 +773,7 @@
// memory error. Fix for bug #1654484
PyType.fromClass(OutOfMemoryError.class);
}
- public static PySystemState defaultSystemState;
+ public static volatile PySystemState defaultSystemState;
// This is a hack to get initializations to work in proper order
public static synchronized boolean initPython() {
PySystemState.initialize();
Modified: trunk/jython/src/org/python/core/PySystemState.java
===================================================================
--- trunk/jython/src/org/python/core/PySystemState.java 2010-09-07 20:49:59 UTC (rev 7111)
+++ trunk/jython/src/org/python/core/PySystemState.java 2010-09-08 06:27:14 UTC (rev 7112)
@@ -7,6 +7,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.net.URLDecoder;
@@ -21,11 +23,11 @@
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
+import java.util.concurrent.ConcurrentMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
-import com.google.common.base.FinalizablePhantomReference;
-import com.google.common.base.FinalizableReferenceQueue;
+import com.google.common.collect.MapMaker;
import org.jruby.ext.posix.util.Platform;
import org.python.Version;
import org.python.core.adapter.ClassicPyObjectAdapter;
@@ -153,9 +155,12 @@
// Automatically close resources associated with a PySystemState when they get GCed
private final PySystemStateCloser closer;
- private static final FinalizableReferenceQueue systemStateQueue = new FinalizableReferenceQueue();
+ private static final ReferenceQueue systemStateQueue = new ReferenceQueue<PySystemState>();
+ private static final ConcurrentMap<WeakReference<PySystemState>, PySystemStateCloser> sysClosers = Generic.concurrentMap();
+// static {
+// startCleanupThread();
+// }
-
public PySystemState() {
initialize();
closer = new PySystemStateCloser(this);
@@ -1251,36 +1256,60 @@
return closer.unregisterCloser(resourceCloser);
}
- public void shutdown() {
- closer.shutdown();
+ public void cleanup() {
+ closer.cleanup();
}
+ private static void startCleanupThread() {
+ Thread cleanupThread = new Thread(new Runnable() {
+ public void run() {
+ while (true) {
+ try {
+ Reference<PySystemStateCloser> ref = systemStateQueue.remove();
+ PySystemStateCloser closer = sysClosers.get(ref);
+ closer.cleanup();
+ sysClosers.remove(ref);
+ } catch (InterruptedException ex) {
+ break;
+ }
+ }
+ }
+ });
+ cleanupThread.setDaemon(true);
+ cleanupThread.start();
+ }
private static class PySystemStateCloser {
private final ArrayList<WeakReference<ThreadState[]>> threadStateList = new ArrayList<WeakReference<ThreadState[]>>();
private final Set<Callable> resourceClosers = new LinkedHashSet<Callable>();
- private final FinalizablePhantomReference<PySystemState> sys;
- private volatile boolean isShutdown = false;
+ private volatile boolean isCleanup = false;
+ private final Thread shutdownHook;
private PySystemStateCloser(PySystemState sys) {
- this.sys = new FinalizablePhantomReference<PySystemState>(sys, systemStateQueue) {
- public void finalizeReferent() {
- shutdown();
- }
- };
- initShutdownCloser();
+ shutdownHook = initShutdownCloser();
+ WeakReference<PySystemState> ref = new WeakReference(sys, systemStateQueue);
+ sysClosers.put(ref, this);
+ cleanupOtherClosers();
}
+ private static void cleanupOtherClosers() {
+ Reference<PySystemStateCloser> ref;
+ while ((ref = systemStateQueue.poll()) != null) {
+ PySystemStateCloser closer = sysClosers.get(ref);
+ closer.cleanup();
+ }
+ }
+
private synchronized void registerThreadState(ThreadState[] threadLocal, ThreadState ts) {
- if (!isShutdown) { // is this really necessary?
+ if (!isCleanup) {
threadLocal[0] = ts;
threadStateList.add(new WeakReference<ThreadState[]>(threadLocal));
}
}
private synchronized void registerCloser(Callable closer) {
- if (!isShutdown) {
+ if (!isCleanup) {
resourceClosers.add(closer);
}
}
@@ -1289,12 +1318,17 @@
return resourceClosers.remove(closer);
}
- private synchronized void shutdown() {
- if (isShutdown) {
+ private synchronized void cleanup() {
+ if (isCleanup) {
return;
}
- isShutdown = true;
+ isCleanup = true;
+ // close this thread so we can unload any associated classloaders in cycle with this instance
+ if (shutdownHook != null) {
+ Runtime.getRuntime().removeShutdownHook(shutdownHook);
+ }
+
// clear out existing ThreadStates so that they can be GCed - this resolves ClassLoader issues
for (WeakReference<ThreadState[]> ref : threadStateList) {
ThreadState[] o = ref.get();
@@ -1308,18 +1342,21 @@
try {
callable.call();
} catch (Exception e) {
- // just continue
+ // just continue, nothing we can do
}
}
resourceClosers.clear();
}
- // Python scripts expect that files are closed upon an orderly shutdown of the VM.
- private void initShutdownCloser() {
+ // Python scripts expect that files are closed upon an orderly cleanup of the VM.
+ private Thread initShutdownCloser() {
try {
- Runtime.getRuntime().addShutdownHook(new ShutdownCloser());
+ Thread shutdownHook = new ShutdownCloser();
+ Runtime.getRuntime().addShutdownHook(shutdownHook);
+ return shutdownHook;
} catch (SecurityException se) {
- Py.writeDebug("PySystemState", "Can't register shutdown closer hook");
+ Py.writeDebug("PySystemState", "Can't register cleanup closer hook");
+ return null;
}
}
Modified: trunk/jython/src/org/python/util/PythonInterpreter.java
===================================================================
--- trunk/jython/src/org/python/util/PythonInterpreter.java 2010-09-07 20:49:59 UTC (rev 7111)
+++ trunk/jython/src/org/python/util/PythonInterpreter.java 2010-09-08 06:27:14 UTC (rev 7112)
@@ -340,16 +340,18 @@
public void cleanup() {
setSystemState();
- Py.getSystemState().callExitFunc();
+ PySystemState sys = Py.getSystemState();
+ sys.callExitFunc();
try {
- Py.getSystemState().stdout.invoke("flush");
+ sys.stdout.invoke("flush");
} catch (PyException pye) {
// fall through
}
try {
- Py.getSystemState().stderr.invoke("flush");
+ sys.stderr.invoke("flush");
} catch (PyException pye) {
// fall through
}
+ sys.cleanup();
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
------------------------------------------------------------------------------
This SF.net Dev2Dev email is sponsored by:
Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd