[Jython-checkins] jython (merge default -> default): Merged trunk
jim.baker
jython-checkins at python.org
Wed Feb 18 08:38:20 CET 2015
https://hg.python.org/jython/rev/f01ff62e8931
changeset: 7587:f01ff62e8931
parent: 7586:a5e9aecc8d9c
parent: 7585:efda62bbec80
user: Jim Baker <jim.baker at rackspace.com>
date: Tue Feb 17 23:55:47 2015 -0700
summary:
Merged trunk
files:
.hgtags | 2 +
Lib/test/test_gc.py | 259 +++--
Lib/test/test_gc_jy.py | 209 ++--
src/org/python/core/JyAttribute.java | 74 +-
src/org/python/core/PyBytecode.java | 15 +-
src/org/python/core/PyObject.java | 23 +-
src/org/python/core/Traverseproc.java | 18 +-
src/org/python/core/TraverseprocDerived.java | 24 +-
src/org/python/core/Visitproc.java | 8 +-
src/org/python/core/finalization/FinalizeTrigger.java | 38 +-
src/org/python/modules/_weakref/AbstractReference.java | 27 +-
src/org/python/modules/_weakref/GlobalRef.java | 79 +-
src/org/python/modules/_weakref/ReferenceType.java | 6 +-
src/org/python/modules/gc.java | 425 +++++++++-
14 files changed, 816 insertions(+), 391 deletions(-)
diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -84,3 +84,5 @@
6e650bf6302fbc142e9fa0397ac2e8f342e16aaf v2.7b4
6e650bf6302fbc142e9fa0397ac2e8f342e16aaf v2.7b4
e270e881c84cbe519035c215fde09677362a4953 v2.7b4
+e270e881c84cbe519035c215fde09677362a4953 v2.7b4
+17d18c6dde9693129d977affb8ca20406d6a6585 v2.7b4
diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py
--- a/Lib/test/test_gc.py
+++ b/Lib/test/test_gc.py
@@ -1,9 +1,10 @@
import unittest
-#from test.test_support import verbose, run_unittest
+from test.test_support import verbose, run_unittest
from test import test_support
import sys
import gc
import weakref
+import time
try:
import threading
@@ -59,6 +60,7 @@
@classmethod
def tearDownClass(cls):
+ #Jython-specific block:
try:
gc.setJythonGCFlags(cls.savedJythonGCFlags)
gc.stopMonitoring()
@@ -203,17 +205,12 @@
self.assertEqual(gc.collect(), 2)
def test_frame(self):
- flg = gc.getJythonGCFlags()
- #gc.addJythonGCFlags(gc.VERBOSE)
- #sporadically fails in Jython, no idea why.
def f():
frame = sys._getframe()
gc.collect()
f()
col = gc.collect()
- gc.setJythonGCFlags(flg)
self.assertEqual(col, 1)
-
def test_saveall(self):
# Verify that cyclic garbage like lists show up in gc.garbage if the
@@ -316,104 +313,115 @@
gc.collect(2)
assertEqual(gc.get_count(), (0, 0, 0))
-# def test_trashcan(self):
-# class Ouch:
-# n = 0
-# def __del__(self):
-# Ouch.n = Ouch.n + 1
-# if Ouch.n % 17 == 0:
-# gc.collect()
-#
-# # "trashcan" is a hack to prevent stack overflow when deallocating
-# # very deeply nested tuples etc. It works in part by abusing the
-# # type pointer and refcount fields, and that can yield horrible
-# # problems when gc tries to traverse the structures.
-# # If this test fails (as it does in 2.0, 2.1 and 2.2), it will
-# # most likely die via segfault.
-#
-# # Note: In 2.3 the possibility for compiling without cyclic gc was
-# # removed, and that in turn allows the trashcan mechanism to work
-# # via much simpler means (e.g., it never abuses the type pointer or
-# # refcount fields anymore). Since it's much less likely to cause a
-# # problem now, the various constants in this expensive (we force a lot
-# # of full collections) test are cut back from the 2.2 version.
-# gc.enable()
-# N = 150
-# for count in range(2):
-# t = []
-# for i in range(N):
-# t = [t, Ouch()]
-# u = []
-# for i in range(N):
-# u = [u, Ouch()]
-# v = {}
-# for i in range(N):
-# v = {1: v, 2: Ouch()}
-# gc.disable()
+ def test_trashcan(self):
+ class Ouch:
+ n = 0
+ def __del__(self):
+ Ouch.n = Ouch.n + 1
+ if Ouch.n % 17 == 0:
+ gc.collect()
+
+ # "trashcan" is a hack to prevent stack overflow when deallocating
+ # very deeply nested tuples etc. It works in part by abusing the
+ # type pointer and refcount fields, and that can yield horrible
+ # problems when gc tries to traverse the structures.
+ # If this test fails (as it does in 2.0, 2.1 and 2.2), it will
+ # most likely die via segfault.
+
+ # Note: In 2.3 the possibility for compiling without cyclic gc was
+ # removed, and that in turn allows the trashcan mechanism to work
+ # via much simpler means (e.g., it never abuses the type pointer or
+ # refcount fields anymore). Since it's much less likely to cause a
+ # problem now, the various constants in this expensive (we force a lot
+ # of full collections) test are cut back from the 2.2 version.
+ gc.enable()
+ N = 150
+ for count in range(2):
+ t = []
+ for i in range(N):
+ t = [t, Ouch()]
+ u = []
+ for i in range(N):
+ u = [u, Ouch()]
+ v = {}
+ for i in range(N):
+ v = {1: v, 2: Ouch()}
+ try:
+ gc.disable()
+ except NotImplementedError:
+ #i.e. Jython is running (or other non-CPython interpreter without gc-disabling)
+ pass
-# @unittest.skipUnless(threading, "test meaningless on builds without threads")
-# def test_trashcan_threads(self):
-# # Issue #13992: trashcan mechanism should be thread-safe
-# NESTING = 60
-# N_THREADS = 2
-#
-# def sleeper_gen():
-# """A generator that releases the GIL when closed or dealloc'ed."""
-# try:
-# yield
-# finally:
-# time.sleep(0.000001)
-#
-# class C(list):
-# # Appending to a list is atomic, which avoids the use of a lock.
-# inits = []
-# dels = []
-# def __init__(self, alist):
-# self[:] = alist
-# C.inits.append(None)
-# def __del__(self):
-# # This __del__ is called by subtype_dealloc().
-# C.dels.append(None)
-# # `g` will release the GIL when garbage-collected. This
-# # helps assert subtype_dealloc's behaviour when threads
-# # switch in the middle of it.
-# g = sleeper_gen()
-# next(g)
-# # Now that __del__ is finished, subtype_dealloc will proceed
-# # to call list_dealloc, which also uses the trashcan mechanism.
-#
-# def make_nested():
-# """Create a sufficiently nested container object so that the
-# trashcan mechanism is invoked when deallocating it."""
-# x = C([])
-# for i in range(NESTING):
-# x = [C([x])]
-# del x
-#
-# def run_thread():
-# """Exercise make_nested() in a loop."""
-# while not exit:
-# make_nested()
-#
-# old_checkinterval = sys.getcheckinterval()
-# sys.setcheckinterval(3)
-# try:
-# exit = False
-# threads = []
-# for i in range(N_THREADS):
-# t = threading.Thread(target=run_thread)
-# threads.append(t)
-# for t in threads:
-# t.start()
-# time.sleep(1.0)
-# exit = True
-# for t in threads:
-# t.join()
-# finally:
-# pass
-# sys.setcheckinterval(old_checkinterval)
-# gc.collect()
-# self.assertEqual(len(C.inits), len(C.dels))
+ @unittest.skipIf(test_support.is_jython,
+ '''
+ Jython does not have a trashcan mechanism.
+ This test should still not fail but currently does.
+ This is because the massive referencing in this test brings
+ sync gc emulation to its limit. Making this more robust is
+ of no priority for now.
+ ''')
+ @unittest.skipUnless(threading, "test meaningless on builds without threads")
+ def test_trashcan_threads(self):
+ # Issue #13992: trashcan mechanism should be thread-safe
+ NESTING = 60
+ N_THREADS = 2
+
+ def sleeper_gen():
+ """A generator that releases the GIL when closed or dealloc'ed."""
+ try:
+ yield
+ finally:
+ time.sleep(0.000001)
+
+ class C(list):
+ # Appending to a list is atomic, which avoids the use of a lock.
+ inits = []
+ dels = []
+ def __init__(self, alist):
+ self[:] = alist
+ C.inits.append(None)
+ def __del__(self):
+ # This __del__ is called by subtype_dealloc().
+ C.dels.append(None)
+ # `g` will release the GIL when garbage-collected. This
+ # helps assert subtype_dealloc's behaviour when threads
+ # switch in the middle of it.
+ g = sleeper_gen()
+ next(g)
+ # Now that __del__ is finished, subtype_dealloc will proceed
+ # to call list_dealloc, which also uses the trashcan mechanism.
+
+ def make_nested():
+ """Create a sufficiently nested container object so that the
+ trashcan mechanism is invoked when deallocating it."""
+ x = C([])
+ for i in range(NESTING):
+ x = [C([x])]
+ del x
+
+ def run_thread():
+ """Exercise make_nested() in a loop."""
+ while not exit:
+ make_nested()
+
+ old_checkinterval = sys.getcheckinterval()
+ sys.setcheckinterval(3)
+ try:
+ exit = False
+ threads = []
+ for i in range(N_THREADS):
+ t = threading.Thread(target=run_thread)
+ threads.append(t)
+ for t in threads:
+ t.start()
+ time.sleep(0.01)
+ exit = True
+ for t in threads:
+ t.join()
+ finally:
+ pass
+ sys.setcheckinterval(old_checkinterval)
+ self.assertEqual(len(C.inits), len(C.dels))
def test_boom(self):
class Boom:
@@ -733,28 +741,29 @@
# empty __dict__.
self.assertEqual(x, None)
-# def test_main():
-# unittest.main()
-# enabled = gc.isenabled()
-# gc.disable()
-# assert not gc.isenabled()
-# debug = gc.get_debug()
-# gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak
-#
-# try:
-# gc.collect() # Delete 2nd generation garbage
-# run_unittest(GCTests, GCTogglingTests)
-# finally:
-# gc.set_debug(debug)
-# # test gc.enable() even if GC is disabled by default
-# if verbose:
-# print "restoring automatic collection"
-# # make sure to always test gc.enable()
-# gc.enable()
-# assert gc.isenabled()
-# if not enabled:
-# gc.disable()
+def test_main():
+ enabled = gc.isenabled()
+ try:
+ gc.disable()
+ assert not gc.isenabled()
+ except NotImplementedError:
+ pass
+ debug = gc.get_debug()
+ gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak
+
+ try:
+ gc.collect() # Delete 2nd generation garbage
+ run_unittest(GCTests, GCTogglingTests)
+ finally:
+ gc.set_debug(debug)
+ # test gc.enable() even if GC is disabled by default
+ if verbose:
+ print "restoring automatic collection"
+ # make sure to always test gc.enable()
+ gc.enable()
+ assert gc.isenabled()
+ if not enabled:
+ gc.disable()
if __name__ == "__main__":
- #test_main()
unittest.main()
diff --git a/Lib/test/test_gc_jy.py b/Lib/test/test_gc_jy.py
--- a/Lib/test/test_gc_jy.py
+++ b/Lib/test/test_gc_jy.py
@@ -1,31 +1,21 @@
"""
Tests some Jython-specific gc aspects and debugging
features.
+Skips and try-blocks assure that this test-script is
+still runnable with CPython and passes there as far
+as not skipped.
"""
import unittest
-#from test.test_support import verbose, run_unittest
-#import sys
+from test import test_support
import time
import gc
import weakref
-from java.lang import System, Runnable
-
-# class FinalizationDummy:
-# def __del__(self):
-# time.sleep(3.5)
-# print "FinalizationDummy.__del__"
-# time.sleep(3.5)
-#
-# class ResurrectionDummy:
-# def __del__(self):
-# print "ResurrectionDummy.__del__"
-# ResurrectionDummy.resurrected = self.toResurrect
-#
-# class SelfResurrectionDummy:
-# def __del__(self):
-# print "SelfResurrectionDummy.__del__"
-# SelfResurrectionDummy.resurrected = self
+try:
+ from java.lang import System, Runnable
+except ImportError:
+ #i.e. Jython is running
+ pass
class GCTests_Jy_CyclicGarbage(unittest.TestCase):
@@ -101,6 +91,8 @@
self.fail("didn't find obj in garbage (finalizer)")
gc.garbage.remove(obj)
+ @unittest.skipUnless(test_support.is_jython,
+ 'CPython has no monitor state')
def test_manual_monitoring(self):
# since tuples are immutable we close the loop with a list
l = []
@@ -117,6 +109,8 @@
self.assertEqual(gc.collect(), 1)
+ at unittest.skipUnless(test_support.is_jython,
+ 'CPython has no gc preprocess and postprocess features')
class GCTests_Jy_preprocess_and_postprocess(unittest.TestCase):
def test_finalization_preprocess_and_postprocess(self):
@@ -156,6 +150,82 @@
prePr = PreProcess()
postPr = PostProcess()
time.sleep(1) # <- to avoid that the newly registered processes
+ # become subject to previous run (remember: We
+ # are not in monitor-mode, i.e. gc runs async.
+ gc.registerPreFinalizationProcess(prePr)
+ gc.registerPostFinalizationProcess(postPr)
+ #Note that order matters here:
+ #If the flag gc.DONT_FINALIZE_RESURRECTED_OBJECTS is used,
+ #gc.registerPostFinalizationProcess(postPr, 0) would lead to failure,
+ #because postPr asserts that a's finalizer already ran. Since
+ #DONT_FINALIZE_RESURRECTED_OBJECTS also inserted a postprocess,
+ #to perform delayed finalization, the 0-index would prepend postPr
+ #before the process that actually runs the finalizers.
+ System.gc()
+ #we wait a bit longer here, since PostProcess runs asynchronous
+ #and must wait for the finalizer of A
+ time.sleep(2)
+ self.assertIn("run PostProcess", comments)
+ comments = []
+ gc.unregisterPreFinalizationProcess(prePr)
+ gc.unregisterPostFinalizationProcess(postPr)
+
+
+ at unittest.skipUnless(test_support.is_jython,
+ 'This class tests detailed Jython-specific behavior.')
+class GCTests_Jy_Delayed_Finalization(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ #Jython-specific block:
+ try:
+ cls.savedJythonGCFlags = gc.getJythonGCFlags()
+ #the finalizer-related tests need this flag to pass in Jython:
+ gc.addJythonGCFlags(gc.DONT_FINALIZE_RESURRECTED_OBJECTS)
+ gc.stopMonitoring()
+ except Exception:
+ pass
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ gc.setJythonGCFlags(cls.savedJythonGCFlags)
+ except Exception:
+ pass
+
+ def test_finalization_preprocess_and_postprocess(self):
+ #Note that this test is done here again (already was in another class
+ #in this module), to see that everything works as it should also with
+ #a different flag-context.
+ comments = []
+ self0 = self
+ class A:
+ def __del__(self):
+ self0.assertIn("run PreProcess", comments)
+ comments.append("A del")
+ #let's simulate a time-consuming finalizer
+ #to ensure that post finalization processing
+ #is sensitive to this
+ time.sleep(0.5)
+ comments.append("A del done")
+
+ class PreProcess(Runnable):
+ def run(self):
+ self0.assertEqual(comments, [])
+ comments.append("run PreProcess")
+
+ class PostProcess(Runnable):
+ def run(self):
+ self0.assertIn("run PreProcess", comments)
+ self0.assertIn("A del", comments)
+ self0.assertIn("A del done", comments)
+ comments.append("run PostProcess")
+
+ a = A()
+ a = None
+ prePr = PreProcess()
+ postPr = PostProcess()
+ time.sleep(1) # <- to avoid that the newly registered processes
# become subject to previous run
gc.registerPreFinalizationProcess(prePr)
gc.registerPostFinalizationProcess(postPr)
@@ -176,86 +246,7 @@
gc.unregisterPostFinalizationProcess(postPr)
-class GCTests_Jy_Delayed_Finalization(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- #Jython-specific block:
- try:
- cls.savedJythonGCFlags = gc.getJythonGCFlags()
- #the finalizer-related tests need this flag to pass in Jython:
- gc.addJythonGCFlags(gc.DONT_FINALIZE_RESURRECTED_OBJECTS)
- gc.stopMonitoring()
- except Exception:
- pass
-
- @classmethod
- def tearDownClass(cls):
- try:
- gc.setJythonGCFlags(cls.savedJythonGCFlags)
- except Exception:
- pass
-
- def test_finalization_preprocess_and_postprocess(self):
- #print "test_finalization_preprocess_and_postprocess"
- #Note that this test is done here again (already was in another class
- #in this module), to see that everything works as it should also with
- #a different flag-context.
- #print "test_finalization_preprocess_and_postprocess"
- #gc.removeJythonGCFlags(gc.DONT_FINALIZE_RESURRECTED_OBJECTS)
- comments = []
- self0 = self
- class A:
- def __del__(self):
- #print "del A"
- self0.assertIn("run PreProcess", comments)
- comments.append("A del")
- #let's simulate a time-consuming finalizer
- #to ensure that post finalization processing
- #is sensitive to this
- time.sleep(0.5)
- comments.append("A del done")
-
- class PreProcess(Runnable):
- def run(self):
- self0.assertEqual(comments, [])
- comments.append("run PreProcess")
-
- class PostProcess(Runnable):
- def run(self):
- self0.assertIn("run PreProcess", comments)
- self0.assertIn("A del", comments)
- self0.assertIn("A del done", comments)
- comments.append("run PostProcess")
-
- a = A()
- a = None
- prePr = PreProcess()
- postPr = PostProcess()
- time.sleep(1) # <- to avoid that the newly registered processes
- # become subject to previous run
- gc.registerPreFinalizationProcess(prePr)
- gc.registerPostFinalizationProcess(postPr)
- #Note that order matters here:
- #If the flag gc.DONT_FINALIZE_RESURRECTED_OBJECTS is used,
- #gc.registerPostFinalizationProcess(postPr, 0) would lead to failure,
- #because postPr asserts that a's finalizer already ran. Since
- #DONT_FINALIZE_RESURRECTED_OBJECTS also inserted a postprocess,
- #to perform delayed finalization, the 0-index would prepend postPr
- #before the process that actually runs the finalizers.
- System.gc()
- #we wait a bit longer here, since PostProcess runs asynchronous
- #and must wait for the finalizer of A
- time.sleep(2)
- self.assertIn("run PostProcess", comments)
- comments = []
- gc.unregisterPreFinalizationProcess(prePr)
- gc.unregisterPostFinalizationProcess(postPr)
-
-
def test_delayedFinalization(self):
- #gc.addJythonGCFlags(gc.DONT_FINALIZE_RESURRECTED_OBJECTS)
- #gc.addJythonGCFlags(gc.VERBOSE)
resurrect = []
comments = []
@@ -291,15 +282,17 @@
del c
self.assertNotEqual(gc.collect(), 0)
time.sleep(1)
- #print comments
- #print resurrect
+ #Note that CPython would collect a, b and c in one run.
+ #With gc.DONT_FINALIZE_RESURRECTED_OBJECTS set, Jython
+ #Would not collect a and b in the same run with c
+ #because a and b might have been resurrected by c and
+ #Java allows not to detect such resurrection in any
+ #other way than waiting for the next gc-run.
self.assertIn('del c', comments)
self.assertEqual(1, len(comments))
comments = []
self.assertNotEqual(gc.collect(), 0)
time.sleep(1)
- #print comments
- #print resurrect
self.assertIn('del a', comments)
self.assertEqual(1, len(comments))
comments = []
@@ -307,8 +300,6 @@
time.sleep(1)
self.assertIn('del b', comments)
self.assertEqual(1, len(comments))
- #gc.removeJythonGCFlags(gc.DONT_FINALIZE_RESURRECTED_OBJECTS)
- #gc.removeJythonGCFlags(gc.VERBOSE)
class GCTests_Jy_Monitoring(unittest.TestCase):
@@ -336,6 +327,7 @@
except Exception:
pass
+ @unittest.skipUnless(test_support.is_jython, 'CPython has no monitor-state.')
def test_monitor_status_after_delayed_finalization(self):
resurrect = []
comments = []
@@ -409,8 +401,11 @@
a.b.lst = lst
del lst
del lst1
- self.assertTrue(gc.isMonitored(a))
- self.assertTrue(gc.isMonitored(a.b))
+ try:
+ self.assertTrue(gc.isMonitored(a))
+ self.assertTrue(gc.isMonitored(a.b))
+ except AttributeError:
+ pass
del a
self.assertEqual(gc.collect(), 2) # c is not cyclic and a, b are resurrected,
# the cycle of two lists is counted here
@@ -543,6 +538,7 @@
except Exception:
pass
+ @unittest.skipUnless(test_support.is_jython, '')
def test_weakref_after_resurrection_threadsafe(self):
resurrect = []
comments = []
@@ -587,7 +583,6 @@
# restored or the deletion is confirmed.
except Exception:
pass
- #self.assertEqual(str(wa()), '<a>')
self.assertEqual(comments, [])
self.assertEqual(resurrect, [])
while comments == [] or resurrect == []:
diff --git a/src/org/python/core/JyAttribute.java b/src/org/python/core/JyAttribute.java
--- a/src/org/python/core/JyAttribute.java
+++ b/src/org/python/core/JyAttribute.java
@@ -4,16 +4,18 @@
/**
* <p>
- * Manages a linked list of general purpose Object-attributes, which
- * can be attached to arbitrary {@code PyObject}s. This method replaces
- * the formerly used method of maintaining weak hash maps for such cases.
- * These weak hash maps were used to map {@code PyObject}s to such
- * attributes, for instance to attach
+ * Manages a linked list of general purpose Object-attributes that
+ * can be attached to arbitrary {@link org.python.core.PyObject}s.
+ * This method replaces the formerly used method of maintaining weak
+ * hash-maps ({@link java.util.WeakHashMap}) for such cases.
+ * These weak hash-maps were used to map
+ * {@code PyObject}s to such attributes, for instance
+ * to attach
* {@link org.python.modules._weakref.GlobalRef}-objects in the
* {@link org.python.modules._weakref.WeakrefModule}.
* </p>
* <p>
- * Attributes attached via the weak hash map method break, if the
+ * Attributes attached via the weak hash-map-method break, if the
* {@code PyObject} is resurrected in its finalizer. The
* {@code JyAttribute}-method is resurrection-safe.
* </p>
@@ -35,18 +37,18 @@
public static final byte JAVA_PROXY_ATTR = Byte.MIN_VALUE;
/**
- * Stores list of weak references linking to this PyObject.
+ * Stores list of weak references linking to this {@code PyObject}.
* This list is weakref-based, so it does not keep the
* weakrefs alive. This is the only way to find out which
* weakrefs (i.e. org.python.modules._weakref.AbstractReference)
* linked to the object after a resurrection. A weak
- * hashmap-based approach for this purpose would break on
+ * hash-map-based approach for this purpose would break on
* resurrection.
*/
public static final byte WEAK_REF_ATTR = 0; //first transient
/**
- * Reserved for use by JyNI.
+ * Reserved for use by <a href="http://www.jyni.org">JyNI</a>.
*/
public static final byte JYNI_HANDLE_ATTR = 1;
@@ -57,8 +59,9 @@
public static final byte PY_ID_ATTR = 2;
/**
- * Holds the current thread for an AbstractReference while
- * referent-retrieval is pending due to a potentially
+ * Holds the current thread for an
+ * {@link org.python.modules._weakref.AbstractReference}
+ * while referent-retrieval is pending due to a potentially
* restored-by-resurrection weak reference. After the
* restore has happened or the clear was confirmed, the
* thread is interrupted and the attribute is cleared.
@@ -66,34 +69,28 @@
public static final byte WEAKREF_PENDING_GET_ATTR = 3;
/**
- * Used by gc module to mark cyclic trash. Searching for cyclic
- * trash is usually not required by Jython. It is only done if
- * gc features are enabled that mimic CPython behavior.
+ * Used by {@link org.python.modules.gc}-module to mark cyclic
+ * trash. Searching for cyclic trash is usually not required
+ * by Jython. It is only done if gc-features are enabled that
+ * mimic CPython behavior.
*/
public static final byte GC_CYCLE_MARK_ATTR = 4;
/**
- * Used by gc module to mark monitored objects before they
- * become unmonitored for deletion. In case of a resurrection
- * this is the only way for gc to detect that the object was
- * to be monitored and should be monitored again.
+ * Used by {@link org.python.modules.gc}-module to mark
+ * finalizable objects that might have been resurrected
+ * during a delayed finalization process.
*/
- //public static final byte GC_MONITOR_MARK_ATTR = 5;
-
- /**
- * Used by gc module to mark finalizable objects that might have
- * been resurrected during a delayed finalization process.
- */
- public static final byte GC_DELAYED_FINALIZE_CRITIC_MARK_ATTR = 6;
+ public static final byte GC_DELAYED_FINALIZE_CRITIC_MARK_ATTR = 5;
public static final byte FINALIZE_TRIGGER_ATTR = Byte.MAX_VALUE;
private static byte nonBuiltinAttrTypeOffset = Byte.MIN_VALUE+1;
- private static byte nonBuiltinTransientAttrTypeOffset = 7;
+ private static byte nonBuiltinTransientAttrTypeOffset = 6;
/**
- * Reserves and returns a new attr type for custom use.
+ * Reserves and returns a new non-transient attr type for custom use.
*
- * @return an attr type for custom use
+ * @return a non-transient attr type for custom use
*/
public static byte reserveCustomAttrType() {
if (nonBuiltinAttrTypeOffset == 0) {
@@ -178,8 +175,8 @@
protected abstract void setValue(Object value);
/**
- * Checks whether the given {@code PyObject} has an attribute
- * of the given type attached.
+ * Checks whether the given {@link org.python.core.PyObject}
+ * has an attribute of the given type attached.
*/
public static synchronized boolean hasAttr(PyObject ob, byte attr_type) {
if (ob.attributes == null) {
@@ -197,7 +194,7 @@
/**
* Retrieves the attribute of the given type from the given
- * {@code PyObject}.
+ * {@link org.python.core.PyObject}.
* If no attribute of the given type is attached, null is returned.
*/
public static synchronized Object getAttr(PyObject ob, byte attr_type) {
@@ -214,6 +211,11 @@
return att != null && att.attr_type == attr_type ? att.getValue() : null;
}
+ /**
+ * Prints the current state of the attribute-list of the
+ * given object to the given stream.
+ * (Intended for debugging)
+ */
public static synchronized void debugPrintAttributes(PyObject o, java.io.PrintStream out) {
out.println("debugPrintAttributes of "+System.identityHashCode(o)+":");
if (o.attributes == null) {
@@ -230,6 +232,11 @@
out.println("debugPrintAttributes done");
}
+ /**
+ * Sets the attribute of type {@code attr_type} in {@code ob} to {@code value}.
+ * If no corresponding attribute exists yet, one is created. If {@value == null},
+ * the attribute is removed (if it existed at all).
+ */
public static synchronized void setAttr(PyObject ob, byte attr_type, Object value) {
if (value == null) {
delAttr(ob, attr_type);
@@ -281,6 +288,11 @@
}
}
+ /**
+ * Removes the attribute of given type from the given object's attribute-list
+ * (if it existed at all). This is equivalent to calling
+ * {@code setAttr(ob, attr_type, null)}.
+ */
public static synchronized void delAttr(PyObject ob, byte attr_type) {
if (ob.attributes == null) {
return;
diff --git a/src/org/python/core/PyBytecode.java b/src/org/python/core/PyBytecode.java
--- a/src/org/python/core/PyBytecode.java
+++ b/src/org/python/core/PyBytecode.java
@@ -164,13 +164,13 @@
enum Why {
- NOT, /* No error */
+ NOT, /* No error */
EXCEPTION, /* Exception occurred */
- RERAISE, /* Exception re-raised by 'finally' */
- RETURN, /* 'return' statement */
- BREAK, /* 'break' statement */
- CONTINUE, /* 'continue' statement */
- YIELD /* 'yield' operator */
+ RERAISE, /* Exception re-raised by 'finally' */
+ RETURN, /* 'return' statement */
+ BREAK, /* 'break' statement */
+ CONTINUE, /* 'continue' statement */
+ YIELD /* 'yield' operator */
};
@@ -1054,7 +1054,8 @@
break;
case Opcode.WITH_CLEANUP: {
- /* TOP is the context.__exit__ bound method.
+ /*
+ TOP is the context.__exit__ bound method.
Below that are 1-3 values indicating how/why
we entered the finally clause:
- SECOND = None
diff --git a/src/org/python/core/PyObject.java b/src/org/python/core/PyObject.java
--- a/src/org/python/core/PyObject.java
+++ b/src/org/python/core/PyObject.java
@@ -20,7 +20,7 @@
/**
* All objects known to the Jython runtime system are represented by an instance
- * of the class <code>PyObject</code> or one of its subclasses.
+ * of the class {@code PyObject} or one of its subclasses.
*/
@ExposedType(name = "object", doc = BuiltinDocs.object_doc)
public class PyObject implements Serializable {
@@ -28,10 +28,14 @@
public static final PyType TYPE = PyType.fromClass(PyObject.class);
/**
- * This should have been suited at org.python.modules.gc, but that would cause
- * a dependency cycle in the init-phases of gc.class and PyObject.class.
- * Now this boolean mirrors the presence of the MONITOR_GLOBAL-flag of
- * Jython's gc module.
+ * This should have been suited at {@link org.python.modules.gc},
+ * but that would cause a dependency cycle in the init-phases of
+ * {@code gc.class} and {@code PyObject.class}. Now this boolean
+ * mirrors the presence of the
+ * {@link org.python.modules.gc#MONITOR_GLOBAL}-flag in Jython's
+ * gc module.<br>
+ * <br>
+ * <b>Do not change manually.</b>
*/
public static boolean gcMonitorGlobal = false;
@@ -45,12 +49,15 @@
* objects can be accessed by the methods and keys in
* {@link org.python.core.JyAttribute}.
* A notable attribute is the javaProxy (accessible via
- * {@code JyAttribute.getAttr(this, JAVA_PROXY_ATTR)}),
+ * {@code JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR)}),
* an underlying Java instance that this object is wrapping or is a
* subclass of. Anything attempting to use the proxy should go through
* {@link #getJavaProxy()} which ensures that it's initialized.
+ *
+ * @see org.python.core.JyAttribute
+ * @see org.python.core.JyAttribute#JAVA_PROXY_ATTR
+ * @see #getJavaProxy()
*/
- //protected Object javaProxy;
protected Object attributes;
/** Primitives classes their wrapper classes. */
@@ -1708,7 +1715,6 @@
public PyObject _is(PyObject o) {
// Access javaProxy directly here as is is for object identity, and at best getJavaProxy
// will initialize a new object with a different identity
- //return this == o || (javaProxy != null && javaProxy == o.javaProxy) ? Py.True : Py.False;
return this == o || (JyAttribute.hasAttr(this, JyAttribute.JAVA_PROXY_ATTR) &&
JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR) ==
JyAttribute.getAttr(o, JyAttribute.JAVA_PROXY_ATTR)) ? Py.True : Py.False;
@@ -1723,7 +1729,6 @@
public PyObject _isnot(PyObject o) {
// Access javaProxy directly here as is is for object identity, and at best getJavaProxy
// will initialize a new object with a different identity
- //return this != o && (javaProxy == null || javaProxy != o.javaProxy) ? Py.True : Py.False;
return this != o && (!JyAttribute.hasAttr(this, JyAttribute.JAVA_PROXY_ATTR) ||
JyAttribute.getAttr(this, JyAttribute.JAVA_PROXY_ATTR) !=
JyAttribute.getAttr(o, JyAttribute.JAVA_PROXY_ATTR)) ? Py.True : Py.False;
diff --git a/src/org/python/core/Traverseproc.java b/src/org/python/core/Traverseproc.java
--- a/src/org/python/core/Traverseproc.java
+++ b/src/org/python/core/Traverseproc.java
@@ -20,8 +20,7 @@
* tracefunc in {@link org.python.core.PyFrame}).
* PyObjects that don't own references to other PyObjects under any condition
* and neither inherit such references from a superclass are strictly recommended
- * to be annotated {@code {@literal @}Untraversable}
- * (see {@link org.python.core.Untraversable} for details).
+ * to be annotated {@link org.python.core.Untraversable}.
* </p>
* <p>
* Jython's traverse mechanism serves debugging purposes to ease finding memory
@@ -42,14 +41,16 @@
* Note that the slots-array and - if existent - the user-dict of fooDerived classes
* is traversed by {@link org.python.core.TraverseProcDerived}.
* The gc module takes care of exploiting both traverse methods in its static traverse
- * method. So for manual traversion one should always use {@code gc.traverse} rather
+ * method. So for manual traversion one should always use
+ * {@link org.python.modules.gc#traverse(PyObject, Visitproc, Object)} rather
* than directly calling methods in this interface.
* </p>
* <p>
- * Also note that {@code objtype} is not subject to {@code Traverseproc}s
- * by default. In CPython only objects with heap-types traverse their
- * ob_type field. In Jython, {@code fooDerived}-classes are the
- * equivalents of heapTypes. For such classes, objtype is actually
+ * Also note that {@link org.python.core.PyObject#objtype} is not subject to
+ * {@code Traverseproc}s by default. In CPython only objects with heap-types
+ * traverse their {@code ob_type}-field. In Jython, {@code fooDerived}-classes
+ * are the equivalents of heapTypes. For such classes
+ * {@link org.python.core.PyObject#objtype} is actually
* traversed (along with the user dict).
* </p>
* <p>
@@ -439,6 +440,9 @@
* UAdd - no refs, extends PythonTree<br>
* USub - no refs, extends PythonTree<br>
* </p>
+ * @see org.python.core.Untraversable
+ * @see org.python.core.Visitproc
+ * @see org.python.modules.gc#traverse(PyObject, Visitproc, Object)
*/
public interface Traverseproc {
diff --git a/src/org/python/core/TraverseprocDerived.java b/src/org/python/core/TraverseprocDerived.java
--- a/src/org/python/core/TraverseprocDerived.java
+++ b/src/org/python/core/TraverseprocDerived.java
@@ -1,17 +1,19 @@
package org.python.core;
/**
- * This is used like Traverseproc, but traverses only the slots[] array
- * of fooDerived classes. This way it is avoided that the traverse
- * method of a traversable PyObject is overwritten by the derived
- * version. The gc module takes care of exploiting both traverse methods.
- *
+ * This is used like {@link org.python.core.Traverseproc},
+ * but traverses only the {@code slots[]}-array of
+ * {@code fooDerived}-classes. This way we avoid that the traverse
+ * method of a traversable {@link org.python.core.PyObject} is
+ * overwritten by the derived version.
+ * {@link org.python.modules.gc#traverse(PyObject, Visitproc, Object)} takes care of
+ * exploiting both traverse methods.
*/
public interface TraverseprocDerived {
- /**
- * Traverses all reachable {@code PyObject}s.
- * Like in CPython, {@code arg} must be passed
- * unmodified to {@code visit} as its second parameter.
- */
- public int traverseDerived(Visitproc visit, Object arg);
+ /**
+ * Traverses all reachable {@code PyObject}s.
+ * Like in CPython, {@code arg} must be passed
+ * unmodified to {@code visit} as its second parameter.
+ */
+ public int traverseDerived(Visitproc visit, Object arg);
}
diff --git a/src/org/python/core/Visitproc.java b/src/org/python/core/Visitproc.java
--- a/src/org/python/core/Visitproc.java
+++ b/src/org/python/core/Visitproc.java
@@ -1,7 +1,9 @@
package org.python.core;
public interface Visitproc {
- /**Must not be called with {@code null}.
- */
- public int visit(PyObject object, Object arg);
+
+ /**
+ * Must not be called with {@code object == null}.
+ */
+ public int visit(PyObject object, Object arg);
}
diff --git a/src/org/python/core/finalization/FinalizeTrigger.java b/src/org/python/core/finalization/FinalizeTrigger.java
--- a/src/org/python/core/finalization/FinalizeTrigger.java
+++ b/src/org/python/core/finalization/FinalizeTrigger.java
@@ -12,35 +12,15 @@
public class FinalizeTrigger {
/**
* This flag tells the finalize trigger to call
- * gc.notifyFinalize after it called the finalizer.
+ * {@link gc#notifyFinalize(PyObject)} after it called the finalizer.
*/
public static final byte NOTIFY_GC_FLAG = (1<<0);
-
- /**
- * This flag tells the finalize trigger to refrain from actually
- * running the PyObject's {@code __del__} method (or variants for
- * derived or builtins).
- * It can be used to have finalize triggers for debugging and
- * monitoring purposes. The actual purpose is for Jython gc's
- * {@code DONT_FINALIZE_CYCLIC_GARBAGE} flag that tells the gc to emulate
- * CPython's <3.4 policy never to finalize cyclic garbage.
- */
- //public static final byte INHIBIT_FINALIZER_FLAG = (1<<1);
-
- /**
- * Tells the finalizer to add the finalized PyObject to the gc's
- * garbage list. This allows gc to mimic CPython's way to deal
- * with cyclic finalizable objects prior 3.4
- * (c.f. CPython's gc's DEBUG_SAVEALL flag).
- */
- //public static final byte ADD_TO_GARBAGE_LIST_FLAG = (1<<2);
/**
- * Similar to {@code INHIBIT_FINALIZER_FLAG}, but indicates that the
- * underlying PyObject was never intended to be finalized, while
- * {@code INHIBIT_FINALIZER_FLAG} indicates that there actually *is* a
- * finalizer that is just not processed due to special
- * circumstances (i.e. inactive {@code DONT_FINALIZE_CYCLIC_GARBAGE} flag).
+ * Indicates that the underlying PyObject was never intended to be finalized.
+ * It is actually not finalizable and the trigger only exists to notify
+ * {@link org.python.modules.gc} that the underlying object was finalized.
+ * This is needed for some advanced gc-functionality.
*/
public static final byte NOT_FINALIZABLE_FLAG = (1<<3);
@@ -186,7 +166,7 @@
}
}
if ((gc.getJythonGCFlags() & gc.VERBOSE_FINALIZE) != 0) {
- Py.writeDebug("gc", "finalization of "+toFinalize);
+ gc.writeDebug("gc", "finalization of "+toFinalize);
}
if (saveGarbage == 1 || (saveGarbage == 0 &&
(gc.get_debug() & gc.DEBUG_SAVEALL) != 0 && isCyclic())) {
@@ -199,13 +179,13 @@
}
gc.garbage.add(toFinalize);
if ((gc.getJythonGCFlags() & gc.VERBOSE_FINALIZE) != 0) {
- Py.writeDebug("gc", toFinalize+" added to garbage.");
+ gc.writeDebug("gc", toFinalize+" added to garbage.");
}
}
}
if ((flags & NOTIFY_GC_FLAG) != 0) {
if ((gc.getJythonGCFlags() & gc.VERBOSE_FINALIZE) != 0) {
- Py.writeDebug("gc", "notify finalization of "+toFinalize);
+ gc.writeDebug("gc", "notify finalization of "+toFinalize);
}
gc.notifyFinalize(toFinalize);
flags &= ~NOTIFY_GC_FLAG;
@@ -217,7 +197,7 @@
gc.notifyPreFinalization();
if (gc.delayedFinalizationEnabled() && toFinalize != null) {
if ((gc.getJythonGCFlags() & gc.VERBOSE_FINALIZE) != 0) {
- Py.writeDebug("gc", "delayed finalization for "+toFinalize);
+ gc.writeDebug("gc", "delayed finalization for "+toFinalize);
}
gc.registerForDelayedFinalization(toFinalize);
} else {
diff --git a/src/org/python/modules/_weakref/AbstractReference.java b/src/org/python/modules/_weakref/AbstractReference.java
--- a/src/org/python/modules/_weakref/AbstractReference.java
+++ b/src/org/python/modules/_weakref/AbstractReference.java
@@ -84,9 +84,9 @@
return null;
}
if ((gc.getJythonGCFlags() & gc.VERBOSE_WEAKREF) != 0) {
- Py.writeDebug("gc", "pending in get of abstract ref "+this+": "+
- Thread.currentThread().getId());
- }
+ gc.writeDebug("gc", "pending in get of abstract ref "+this+": "+
+ Thread.currentThread().getId());
+ }
JyAttribute.setAttr(this, JyAttribute.WEAKREF_PENDING_GET_ATTR, Thread.currentThread());
while (!gref.cleared && result == null) {
try {
@@ -96,22 +96,23 @@
}
JyAttribute.delAttr(this, JyAttribute.WEAKREF_PENDING_GET_ATTR);
if ((gc.getJythonGCFlags() & gc.VERBOSE_WEAKREF) != 0) {
- Py.writeDebug("gc", "pending of "+this+" resolved: "+
- Thread.currentThread().getId());
- if (gref.cleared) {
- Py.writeDebug("gc", "reference was cleared.");
- } else if (result != null){
- Py.writeDebug("gc", "reference was restored.");
- } else {
- Py.writeDebug("gc", "something went very wrong.");
- }
- }
+ gc.writeDebug("gc", "pending of "+this+" resolved: "+
+ Thread.currentThread().getId());
+ if (gref.cleared) {
+ gc.writeDebug("gc", "reference was cleared.");
+ } else if (result != null){
+ gc.writeDebug("gc", "reference was restored.");
+ } else {
+ gc.writeDebug("gc", "something went very wrong.");
+ }
+ }
return result;
} else {
return result;
}
}
+
/* Traverseproc implementation */
@Override
public int traverse(Visitproc visit, Object arg) {
diff --git a/src/org/python/modules/_weakref/GlobalRef.java b/src/org/python/modules/_weakref/GlobalRef.java
--- a/src/org/python/modules/_weakref/GlobalRef.java
+++ b/src/org/python/modules/_weakref/GlobalRef.java
@@ -20,8 +20,8 @@
public class GlobalRef extends WeakReference<PyObject> {
/**
- * This reference's hashCode: the System.identityHashCode of the referent. Only used
- * internally.
+ * This reference's hashCode: The {@code System.identityHashCode} of the referent.
+ * Only used internally.
*/
private int hashCode;
@@ -31,16 +31,19 @@
*/
private int pythonHashCode;
- /** Whether pythonHashCode was already determined. */
+ /** Whether {@link #pythonHashCode} was already determined. */
private boolean havePythonHashCode;
/**
- * This boolean is set true when the callback is processed. If the reference is
- * cleared it might potentially be restored until this boolean is set true.
- * If weak reference restoring is activated (c.f.
- * gc.PRESERVE_WEAKREFS_ON_RESURRECTION), AbstractReference.get would block
- * until a consistent state is reached (i.e. referent is non-null or
- * cleared == true).
+ * This boolean is set {@code true} when the callback is processed.
+ * If the reference is cleared it might potentially be restored until
+ * this boolean is set true. If weak reference restoring is activated (c.f.
+ * {@link gc#PRESERVE_WEAKREFS_ON_RESURRECTION}), {@link AbstractReference#get()}
+ * would block until a consistent state is reached (i.e. referent is
+ * non-{@code null} or {@code cleared == true}).
+ *
+ * @see gc#PRESERVE_WEAKREFS_ON_RESURRECTION
+ * @see AbstractReference#get()
*/
protected boolean cleared = false;
@@ -73,7 +76,7 @@
* Search for a reusable reference. To be reused, it must be of the
* same class and it must not have a callback.
*/
- synchronized AbstractReference find(Class cls) {
+ synchronized AbstractReference find(Class<?> cls) {
for (int i = references.size() - 1; i >= 0; i--) {
AbstractReference r = getReferenceAt(i);
if (r == null) {
@@ -108,7 +111,10 @@
}
/**
- * Call all callbacks that were enqueued via delayedCallback method.
+ * Call all callbacks that were enqueued via
+ * {@link #delayedCallback(GlobalRef)} method.
+ *
+ * @see #delayedCallback(GlobalRef)
*/
public static void processDelayedCallbacks() {
if (delayedCallbacks != null) {
@@ -123,9 +129,12 @@
/**
* Stores the callback for later processing. This is needed if
- * weak reference restoration (c.f. gc.PRESERVE_WEAKREFS_ON_RESURRECTION)
- * is activated. In this case the callback is delayed until it was
+ * weak reference restoration (c.f.
+ * {@link gc#PRESERVE_WEAKREFS_ON_RESURRECTION})
+ * is active. In this case the callback is delayed until it was
* determined whether a resurrection restored the reference.
+ *
+ * @see gc#PRESERVE_WEAKREFS_ON_RESURRECTION
*/
private static void delayedCallback(GlobalRef cl) {
if (delayedCallbacks == null) {
@@ -164,10 +173,10 @@
}
/**
- * Create a new tracked GlobalRef.
+ * Create a new tracked {@code GlobalRef}.
*
- * @param object a PyObject to reference
- * @return a new tracked GlobalRef
+ * @param object a {@link org.python.core.PyObject} to reference
+ * @return a new tracked {@code GlobalRef}
*/
public static GlobalRef newInstance(PyObject object) {
createReaperThreadIfAbsent();
@@ -188,12 +197,16 @@
/**
* Restores this weak reference to its former referent.
- * This actually means that a fresh GlobalRef is created
- * and inserted into all adjacent AbstractRefs. The
- * current GlobalRef is disbanded.
- * If the given PyObject is not the former referent of
- * this weak reference, an IllegalArgumentException is
- * thrown.
+ * This actually means that a fresh {@code GlobalRef} is created
+ * and inserted into all adjacent
+ * {@link org.python.modules._weakref.AbstractReference}s. The
+ * current {@code GlobalRef} is disbanded.
+ * If the given {@link org.python.core.PyObject} is not the former
+ * referent of this weak reference, an
+ * {@link java.lang.IllegalArgumentException} is thrown.
+ *
+ * @throws java.lang.IllegalArgumentException if {@code formerReferent} is not
+ * the actual former referent.
*/
public void restore(PyObject formerReferent) {
if (JyAttribute.getAttr(formerReferent, JyAttribute.WEAK_REF_ATTR) != this) {
@@ -248,7 +261,8 @@
}
/**
- * Return the number of references to the specified PyObject.
+ * Return the number of references to the specified
+ * {@link org.python.core.PyObject}.
*
* @param object a PyObject
* @return an int reference count
@@ -259,10 +273,11 @@
}
/**
- * Return a list of references to the specified PyObject.
+ * Return a list of references to the specified
+ * {@link org.python.core.PyObject}.
*
- * @param object a PyObject
- * @return a PyList of references. may be empty
+ * @param object a {@link org.python.core.PyObject}
+ * @return a {@link org.python.core.PyList} of references. May be empty.
*/
public static PyList getRefs(PyObject object) {
GlobalRef ref = objects.get(new GlobalRef(object));
@@ -270,7 +285,7 @@
}
/**
- * Allow GlobalRef's to be used as hashtable keys.
+ * Allow {@code GlobalRef}s to be used as hashtable-keys.
*/
public boolean equals(Object o) {
if (this == o) {
@@ -292,18 +307,20 @@
}
/**
- * Allows GlobalRef to be used as hashtable keys.
+ * Allows {@code GlobalRef} to be used as hashtable-keys.
*
- * @return a hashCode int value
+ * @return a hashCode {@code int}-value
*/
public int hashCode() {
return hashCode;
}
/**
- * The publicly used hashCode, for the AbstractReference wrapper.
+ * The publicly used {@code hashCode}, for the
+ * {@link org.python.modules._weakref.AbstractReference}
+ * wrapper.
*
- * @return a hashCode int value
+ * @return a hashCode {@code int}-value
*/
public int pythonHashCode() {
if (havePythonHashCode) {
diff --git a/src/org/python/modules/_weakref/ReferenceType.java b/src/org/python/modules/_weakref/ReferenceType.java
--- a/src/org/python/modules/_weakref/ReferenceType.java
+++ b/src/org/python/modules/_weakref/ReferenceType.java
@@ -68,9 +68,9 @@
* to passthru).
*
* @param funcName the name of the caller
- * @param args PyObject array of args
- * @param keywords String array of keywords
- * @return an ArgParser instance
+ * @param args {@link or.python.core.PyObject} array of args
+ * @param keywords {@code String}-array of keywords
+ * @return an {@link or.python.core.ArgParser} instance
*/
private static ArgParser parseInitArgs(String funcName, PyObject[] args, String[] keywords) {
if (keywords.length > 0) {
diff --git a/src/org/python/modules/gc.java b/src/org/python/modules/gc.java
--- a/src/org/python/modules/gc.java
+++ b/src/org/python/modules/gc.java
@@ -18,6 +18,7 @@
import org.python.core.PyList;
import org.python.core.PyObject;
import org.python.core.PyInstance;
+import org.python.core.PyString;
import org.python.core.Traverseproc;
import org.python.core.TraverseprocDerived;
import org.python.core.Visitproc;
@@ -25,9 +26,11 @@
import org.python.core.finalization.FinalizeTrigger;
import org.python.modules._weakref.GlobalRef;
+import com.sun.management.GarbageCollectionNotificationInfo;
+
public class gc {
/**
- * A constant that can occur as result of {@code gc.collect} and
+ * A constant that can occur as result of {@link #collect()} and
* indicates an unknown number of collected cyclic trash.
* It is intentionally not valued -1 as that value is
* reserved to indicate an error.
@@ -36,9 +39,14 @@
/* Jython-specific gc-flags: */
/**
- * Tells every newly created PyObject to register for
- * gc-monitoring. This allows {@code gc.collect} to report the
+ * This flag tells every newly created PyObject to register for
+ * gc-monitoring. This allows {@link #collect()} to report the
* number of collected objects.
+ *
+ * @see #setJythonGCFlags(short)
+ * @see #getJythonGCFlags()
+ * @see #addJythonGCFlags(short)
+ * @see #removeJythonGCFlags(short)
*/
public static final short MONITOR_GLOBAL = (1<<0);
@@ -47,6 +55,11 @@
* PyObjects, while Jython does this by default. This flag
* tells Jython's gc to mimic CPython <3.4 behavior (i.e.
* add such objects to {@code gc.garbage} list instead).
+ *
+ * @see #setJythonGCFlags(short)
+ * @see #getJythonGCFlags()
+ * @see #addJythonGCFlags(short)
+ * @see #removeJythonGCFlags(short)
*/
public static final short DONT_FINALIZE_CYCLIC_GARBAGE = (1<<1);
@@ -65,6 +78,11 @@
* delay garbage collection of some weak referenced objects
* for several gc cycles if activated. So we recommend to
* use it only for debugging.
+ *
+ * @see #setJythonGCFlags(short)
+ * @see #getJythonGCFlags()
+ * @see #addJythonGCFlags(short)
+ * @see #removeJythonGCFlags(short)
*/
public static final short PRESERVE_WEAKREFS_ON_RESURRECTION = (1<<2);
@@ -80,6 +98,11 @@
* significant cost as it can delay collection of many objects
* for several gc-cycles. Its main intention is for debugging
* resurrection-sensitive code.
+ *
+ * @see #setJythonGCFlags(short)
+ * @see #getJythonGCFlags()
+ * @see #addJythonGCFlags(short)
+ * @see #removeJythonGCFlags(short)
*/
public static final short DONT_FINALIZE_RESURRECTED_OBJECTS = (1<<3);
@@ -88,6 +111,11 @@
* is deactivated by default for now. This means that
* {@code DONT_TRAVERSE_BY_REFLECTION} is set by default.
* Once it is stable, reflection-based traversion will be active by default.
+ *
+ * @see #setJythonGCFlags(short)
+ * @see #getJythonGCFlags()
+ * @see #addJythonGCFlags(short)
+ * @see #removeJythonGCFlags(short)
*/
public static final short DONT_TRAVERSE_BY_REFLECTION = (1<<4);
@@ -109,6 +137,11 @@
* This is because in an ideal implementation reflection-based traversion never
* occurs; it is only an inefficient fallback.
* </p>
+ *
+ * @see #setJythonGCFlags(short)
+ * @see #getJythonGCFlags()
+ * @see #addJythonGCFlags(short)
+ * @see #removeJythonGCFlags(short)
*/
public static final short SUPPRESS_TRAVERSE_BY_REFLECTION_WARNING = (1<<5);
@@ -119,14 +152,65 @@
* gc-messages, no matter what overall verbose level is selected.
* This flag tells Jython to use {@code Py.writeDebug} for debugging output.
* If it is not set (default-case), gc-debugging output (if gc-{@code VERBOSE}
- * or -{@code DEBUG} flags are set) is directly written to {@code System.err}.
+ * or -{@code DEBUG} flags are set) is directly written to {@code System.err}.
+ *
+ * @see #setJythonGCFlags(short)
+ * @see #getJythonGCFlags()
+ * @see #addJythonGCFlags(short)
+ * @see #removeJythonGCFlags(short)
*/
public static final short USE_PY_WRITE_DEBUG = (1<<6);
+ /**
+ * Enables collection-related verbose-output.
+ *
+ * @see #setJythonGCFlags(short)
+ * @see #getJythonGCFlags()
+ * @see #addJythonGCFlags(short)
+ * @see #removeJythonGCFlags(short)
+ */
public static final short VERBOSE_COLLECT = (1<<7);
+
+ /**
+ * Enables weakref-related verbose-output.
+ *
+ * @see #setJythonGCFlags(short)
+ * @see #getJythonGCFlags()
+ * @see #addJythonGCFlags(short)
+ * @see #removeJythonGCFlags(short)
+ */
public static final short VERBOSE_WEAKREF = (1<<8);
+
+ /**
+ * Enables delayed finalization related verbose-output.
+ *
+ * @see #setJythonGCFlags(short)
+ * @see #getJythonGCFlags()
+ * @see #addJythonGCFlags(short)
+ * @see #removeJythonGCFlags(short)
+ */
public static final short VERBOSE_DELAYED = (1<<9);
+
+ /**
+ * Enables finalization-related verbose-output.
+ *
+ * @see #setJythonGCFlags(short)
+ * @see #getJythonGCFlags()
+ * @see #addJythonGCFlags(short)
+ * @see #removeJythonGCFlags(short)
+ */
public static final short VERBOSE_FINALIZE = (1<<10);
+
+ /**
+ * Bit-combination of the flags {@link #VERBOSE_COLLECT},
+ * {@link #VERBOSE_WEAKREF}, {@link #VERBOSE_DELAYED},
+ * {@link #VERBOSE_FINALIZE}.
+ *
+ * @see #setJythonGCFlags(short)
+ * @see #getJythonGCFlags()
+ * @see #addJythonGCFlags(short)
+ * @see #removeJythonGCFlags(short)
+ */
public static final short VERBOSE =
VERBOSE_COLLECT | VERBOSE_WEAKREF | VERBOSE_DELAYED | VERBOSE_FINALIZE;
@@ -134,38 +218,65 @@
/**
* print collection statistics
* (in Jython scoped on monitored objects)
+ *
+ * @see #set_debug(int)
+ * @see #get_debug()
*/
public static final int DEBUG_STATS = (1<<0);
/**
* print collectable objects
* (in Jython scoped on monitored objects)
+ *
+ * @see #set_debug(int)
+ * @see #get_debug()
*/
public static final int DEBUG_COLLECTABLE = (1<<1);
/**
* print uncollectable objects
* (in Jython scoped on monitored objects)
+ *
+ * @see #set_debug(int)
+ * @see #get_debug()
*/
public static final int DEBUG_UNCOLLECTABLE = (1<<2);
/**
* print instances
* (in Jython scoped on monitored objects)
+ *
+ * @see #set_debug(int)
+ * @see #get_debug()
*/
public static final int DEBUG_INSTANCES = (1<<3);
/**
* print other objects
* (in Jython scoped on monitored objects)
+ *
+ * @see #set_debug(int)
+ * @see #get_debug()
*/
public static final int DEBUG_OBJECTS = (1<<4);
/**
* save all garbage in gc.garbage
* (in Jython scoped on monitored objects)
+ *
+ * @see #set_debug(int)
+ * @see #get_debug()
*/
public static final int DEBUG_SAVEALL = (1<<5);
+
+ /**
+ * Bit-combination of the flags {@link #DEBUG_COLLECTABLE},
+ * {@link #DEBUG_UNCOLLECTABLE}, {@link #DEBUG_INSTANCES},
+ * {@link #DEBUG_OBJECTS}, {@link #DEBUG_SAVEALL}.
+ *
+ * @see #set_debug(int)
+ * @see #get_debug()
+ */
public static final int DEBUG_LEAK = DEBUG_COLLECTABLE |
DEBUG_UNCOLLECTABLE |
DEBUG_INSTANCES |
@@ -184,6 +295,10 @@
private static long lastRemoveTimeStamp = -1, maxWaitTime = initWaitTime;
private static int gcMonitoredRunCount = 0;
public static long gcRecallTime = 4000;
+
+ /**
+ * list of uncollectable objects
+ */
public static PyList garbage = new PyList();
//Finalization preprocess/postprocess-related declarations:
@@ -207,17 +322,113 @@
private static boolean notifyRerun = false;
public static final String __doc__ =
- "This module provides access to the garbage collector.\n" +
+ "This module provides access to the garbage collector for reference cycles.\n" +
"\n" +
- "enable() -- Enable automatic garbage collection (does nothing).\n" +
+ "enable() -- Enable automatic garbage collection (does nothing in Jython).\n" +
+ "disable() -- Disable automatic garbage collection (raises NotImplementedError in Jython).\n" +
"isenabled() -- Returns True because Java garbage collection cannot be disabled.\n" +
- "collect() -- Trigger a Java garbage collection (potentially expensive).\n" +
- "get_debug() -- Get debugging flags (returns 0).\n" +
- "\n" +
- "Other functions raise NotImplementedError because they do not apply to Java.\n";
+ "collect() -- Do a full collection right now (potentially expensive).\n" +
+ "get_count() -- Return the current collection counts (raises NotImplementedError in Jython).\n" +
+ "set_debug() -- Set debugging flags.\n" +
+ "get_debug() -- Get debugging flags.\n" +
+ "set_threshold() -- Set the collection thresholds (raise NotImplementedError in Jython).\n" +
+ "get_threshold() -- Return the current the collection thresholds (raise NotImplementedError in Jython).\n" +
+ "get_objects() -- Return a list of all objects tracked by the collector (raises NotImplementedError in Jython).\n" +
+ "is_tracked() -- Returns true if a given object is tracked (i.e. monitored in Jython).\n" +
+ "get_referrers() -- Return the list of objects that refer to an object (only finds monitored referrers in Jython).\n" +
+ "get_referents() -- Return the list of objects that an object refers to.\n";
public static final String __name__ = "gc";
+ public static final PyString __doc__enable = new PyString(
+ "enable() -> None\n" +
+ "\n" +
+ "Enable automatic garbage collection.\n" +
+ "(does nothing in Jython)\n");
+
+ public static final PyString __doc__disable = new PyString(
+ "disable() -> None\n" +
+ "\n" +
+ "Disable automatic garbage collection.\n" +
+ "(raises NotImplementedError in Jython)\n");
+
+ public static final PyString __doc__isenabled = new PyString(
+ "isenabled() -> status\n" +
+ "\n" +
+ "Returns true if automatic garbage collection is enabled.\n");
+
+ public static final PyString __doc__collect = new PyString(
+ "collect([generation]) -> n\n" +
+ "\n" +
+ "With no arguments, run a full collection. The optional argument\n" +
+ "may be an integer specifying which generation to collect. A ValueError\n" +
+ "is raised if the generation number is invalid.\n\n" +
+ "The number of unreachable objects is returned.\n" +
+ "(Jython emulates CPython cyclic trash counting if objects are monitored.\n" +
+ "If no objects are monitored, returns -2\n");
+
+ public static final PyString __doc__get_count = new PyString(
+ "get_count() -> (count0, count1, count2)\n" +
+ "\n" +
+ "Return the current collection counts\n" +
+ "(raises NotImplementedError in Jython)\n");
+
+ public static final PyString __doc__set_debug = new PyString(
+ "set_debug(flags) -> None\n" +
+ "\n" +
+ "Set the garbage collection debugging flags. Debugging information is\n" +
+ "written to sys.stderr.\n" +
+ "\n" +
+ "flags is an integer and can have the following bits turned on:\n" +
+ "\n" +
+ " DEBUG_STATS - Print statistics during collection.\n" +
+ " DEBUG_COLLECTABLE - Print collectable objects found.\n" +
+ " DEBUG_UNCOLLECTABLE - Print unreachable but uncollectable objects found.\n" +
+ " DEBUG_INSTANCES - Print instance objects.\n" +
+ " DEBUG_OBJECTS - Print objects other than instances.\n" +
+ " DEBUG_SAVEALL - Save objects to gc.garbage rather than freeing them.\n" +
+ " DEBUG_LEAK - Debug leaking programs (everything but STATS).\n");
+
+ public static final PyString __doc__get_debug = new PyString(
+ "get_debug() -> flags\n" +
+ "\n" +
+ "Get the garbage collection debugging flags.\n");
+
+ public static final PyString __doc__set_thresh = new PyString(
+ "set_threshold(threshold0, [threshold1, threshold2]) -> None\n" +
+ "\n" +
+ "Sets the collection thresholds. Setting threshold0 to zero disables\n" +
+ "collection.\n" +
+ "(raises NotImplementedError in Jython)\n");
+
+ public static final PyString __doc__get_thresh = new PyString(
+ "get_threshold() -> (threshold0, threshold1, threshold2)\n" +
+ "\n" +
+ "Return the current collection thresholds\n" +
+ "(raises NotImplementedError in Jython)\n");
+
+ public static final PyString __doc__get_objects = new PyString(
+ "get_objects() -> [...]\n" +
+ "\n" +
+ "Return a list of objects tracked by the collector (excluding the list\n" +
+ "returned).\n" +
+ "(raises NotImplementedError in Jython)\n");
+
+ public static final PyString __doc__is_tracked = new PyString(
+ "is_tracked(obj) -> bool\n" +
+ "\n" +
+ "Returns true if the object is tracked by the garbage collector.\n" +
+ "(i.e. monitored in Jython)\n");
+
+ public static final PyString __doc__get_referrers = new PyString(
+ "get_referrers(*objs) -> list\n" +
+ "Return the list of objects that directly refer to any of objs.\n" +
+ "(only finds monitored referrers in Jython)");
+
+ public static final PyString __doc__get_referents = new PyString(
+ "get_referents(*objs) -> list\n" +
+ "Return the list of objects that are directly referred to by objs.");
+
public static class CycleMarkAttr {
private boolean cyclic = false;
@@ -382,7 +593,17 @@
}
}
- private static void writeDebug(String type, String msg) {
+ /**
+ * Works like {@link org.python.core.Py#writeDebug(String, String)},
+ * but prints to {@link org.python.core.Py#writeDebug(String, String)}
+ * (i.e. subject to Jython's verbose level)
+ * or directly to {@code System.err}, according to
+ * {@link #USE_PY_WRITE_DEBUG}.
+ *
+ * @see #USE_PY_WRITE_DEBUG
+ * @see org.python.core.Py#writeDebug(String, String)
+ */
+ public static void writeDebug(String type, String msg) {
if ((gcFlags & USE_PY_WRITE_DEBUG) != 0) {
Py.writeDebug(type, msg);
} else {
@@ -1102,6 +1323,25 @@
//----------end of Monitoring section--------------------------------------
+ /**
+ * Gets the current Jython-specific gc-flags.
+ *
+ * @see #MONITOR_GLOBAL
+ * @see #DONT_FINALIZE_CYCLIC_GARBAGE
+ * @see #PRESERVE_WEAKREFS_ON_RESURRECTION
+ * @see #DONT_FINALIZE_RESURRECTED_OBJECTS
+ * @see #DONT_TRAVERSE_BY_REFLECTION
+ * @see #SUPPRESS_TRAVERSE_BY_REFLECTION_WARNING
+ * @see #USE_PY_WRITE_DEBUG
+ * @see #VERBOSE_COLLECT
+ * @see #VERBOSE_WEAKREF
+ * @see #VERBOSE_DELAYED
+ * @see #VERBOSE_FINALIZE
+ * @see #VERBOSE
+ * @see #setJythonGCFlags(short)
+ * @see #addJythonGCFlags(short)
+ * @see #removeJythonGCFlags(short)
+ */
public static short getJythonGCFlags() {
if (((gcFlags & MONITOR_GLOBAL) != 0) != PyObject.gcMonitorGlobal) {
if (PyObject.gcMonitorGlobal) {
@@ -1113,6 +1353,44 @@
return gcFlags;
}
+ /**
+ * Sets the current Jython-specific gc-flags.
+ * <br>
+ * {@code flags} is a {@code short} and can have the following bits turned on:<br>
+ * <br>
+ * {@link #MONITOR_GLOBAL} - Automatically monitors all PyObjects created from now on.<br>
+ * {@link #DONT_FINALIZE_CYCLIC_GARBAGE} - Adds cyclic finalizable PyObjects to {@link #garbage}.<br>
+ * {@link #PRESERVE_WEAKREFS_ON_RESURRECTION} - Keeps weak references alive if the referent is resurrected.<br>
+ * {@link #DONT_FINALIZE_RESURRECTED_OBJECTS} -
+ * Emulates CPython behavior regarding resurrected objects and finalization.<br>
+ * {@link #DONT_TRAVERSE_BY_REFLECTION} - Inhibits reflection-based traversion.<br>
+ * {@link #SUPPRESS_TRAVERSE_BY_REFLECTION_WARNING} -
+ * Suppress warnings for PyObjects that neither implement {@link org.python.core.Traverseproc} nor
+ * are marked as {@link org.python.core.Untraversable}.<br>
+ * {@link #USE_PY_WRITE_DEBUG} - uses {@link org.python.core.Py#writeDebug(String, String)} for
+ * debugging output instead of directly writing to {@link java.lang.System#err}.<br>
+ * {@link #VERBOSE_COLLECT} - Enable collection-related verbose output.<br>
+ * {@link #VERBOSE_WEAKREF} - Enable weakref-related verbose output.<br>
+ * {@link #VERBOSE_DELAYED} - Enable delayed finalization-related verbose output.<br>
+ * {@link #VERBOSE_FINALIZE} - Enable finalization-related verbose output.<br>
+ * {@link #VERBOSE} - All previous verbose-flags combined.
+ *
+ * @see #MONITOR_GLOBAL
+ * @see #DONT_FINALIZE_CYCLIC_GARBAGE
+ * @see #PRESERVE_WEAKREFS_ON_RESURRECTION
+ * @see #DONT_FINALIZE_RESURRECTED_OBJECTS
+ * @see #DONT_TRAVERSE_BY_REFLECTION
+ * @see #SUPPRESS_TRAVERSE_BY_REFLECTION_WARNING
+ * @see #USE_PY_WRITE_DEBUG
+ * @see #VERBOSE_COLLECT
+ * @see #VERBOSE_WEAKREF
+ * @see #VERBOSE_DELAYED
+ * @see #VERBOSE_FINALIZE
+ * @see #VERBOSE
+ * @see #getJythonGCFlags()
+ * @see #addJythonGCFlags(short)
+ * @see #removeJythonGCFlags(short)
+ */
public static void setJythonGCFlags(short flags) {
gcFlags = flags;
PyObject.gcMonitorGlobal = (gcFlags & MONITOR_GLOBAL) != 0;
@@ -1121,6 +1399,22 @@
/**
* This is a convenience method to add flags via bitwise or.
+ *
+ * @see #MONITOR_GLOBAL
+ * @see #DONT_FINALIZE_CYCLIC_GARBAGE
+ * @see #PRESERVE_WEAKREFS_ON_RESURRECTION
+ * @see #DONT_FINALIZE_RESURRECTED_OBJECTS
+ * @see #DONT_TRAVERSE_BY_REFLECTION
+ * @see #SUPPRESS_TRAVERSE_BY_REFLECTION_WARNING
+ * @see #USE_PY_WRITE_DEBUG
+ * @see #VERBOSE_COLLECT
+ * @see #VERBOSE_WEAKREF
+ * @see #VERBOSE_DELAYED
+ * @see #VERBOSE_FINALIZE
+ * @see #VERBOSE
+ * @see #getJythonGCFlags()
+ * @see #setJythonGCFlags(short)
+ * @see #removeJythonGCFlags(short)
*/
public static void addJythonGCFlags(short flags) {
gcFlags |= flags;
@@ -1130,6 +1424,22 @@
/**
* This is a convenience method to remove flags via bitwise and-not.
+ *
+ * @see #MONITOR_GLOBAL
+ * @see #DONT_FINALIZE_CYCLIC_GARBAGE
+ * @see #PRESERVE_WEAKREFS_ON_RESURRECTION
+ * @see #DONT_FINALIZE_RESURRECTED_OBJECTS
+ * @see #DONT_TRAVERSE_BY_REFLECTION
+ * @see #SUPPRESS_TRAVERSE_BY_REFLECTION_WARNING
+ * @see #USE_PY_WRITE_DEBUG
+ * @see #VERBOSE_COLLECT
+ * @see #VERBOSE_WEAKREF
+ * @see #VERBOSE_DELAYED
+ * @see #VERBOSE_FINALIZE
+ * @see #VERBOSE
+ * @see #getJythonGCFlags()
+ * @see #setJythonGCFlags(short)
+ * @see #addJythonGCFlags(short)
*/
public static void removeJythonGCFlags(short flags) {
gcFlags &= ~flags;
@@ -1161,21 +1471,34 @@
notifyFinalize(abort);
}
+ /**
+ * Does nothing in Jython as Java-gc is always enabled.
+ */
public static void enable() {}
+ /**
+ * Not supported by Jython.
+ * Throws {@link org.python.core.Py#NotImplementedError}.
+ *
+ * @throws org.python.core.Py#NotImplementedError
+ */
public static void disable() {
throw Py.NotImplementedError("can't disable Java GC");
}
+ /**
+ * Always returns {@code true} in Jython.
+ */
public static boolean isenabled() { return true; }
/**
* The generation parameter is only for compatibility with
- * CPython {@code gc.collect} and is ignored.
+ * CPython {@link gc.collect()} and is ignored.
* @param generation (ignored)
* @return Collected monitored cyclic trash-objects or
* {@code gc.UNKNOWN_COUNT} if nothing is monitored or -1 if
* an error occurred and collection did not complete.
+ * @see #collect()
*/
public static int collect(int generation) {
return collect();
@@ -1194,14 +1517,16 @@
/**
* If no objects are monitored, this just delegates to
- * {@code System.gc} and returns {@code gc.UNKNOWN_COUNT} as a
+ * {@code System.gc()} and returns {@link #UNKNOWN_COUNT} as a
* non-erroneous default value. If objects are monitored,
- * it emulates a synchronous gc run in the sense that it waits
+ * it emulates a synchronous gc-run in the sense that it waits
* until all collected monitored objects were finalized.
*
* @return Number of collected monitored cyclic trash-objects
- * or {@code gc.UNKNOWN_COUNT} if nothing is monitored or -1
+ * or {@link #UNKNOWN_COUNT} if nothing is monitored or -1
* if an error occurred and collection did not complete.
+ * @see #UNKNOWN_COUNT
+ * @see #collect(int)
*/
public static int collect() {
try {
@@ -1619,26 +1944,79 @@
stat[1] -= abortedCyclicFinalizers;
}
+ /**
+ * Not supported by Jython.
+ * Throws {@link org.python.core.Py#NotImplementedError}.
+ *
+ * @throws org.python.core.Py#NotImplementedError
+ */
public static PyObject get_count() {
throw Py.NotImplementedError("not applicable to Java GC");
}
+ /**
+ * Copied from CPython-doc:<br>
+ * <br>
+ * Set the garbage collection debugging flags. Debugging information is
+ * written to {@code System.err}.<br>
+ * <br>
+ * {@flags} flags is an {@code int}eger and can have the following bits turned on:<br>
+ * <br>
+ * {@link #DEBUG_STATS} - Print statistics during collection.<br>
+ * {@link #DEBUG_COLLECTABLE} - Print collectable objects found.<br>
+ * {@link #DEBUG_UNCOLLECTABLE} - Print unreachable but uncollectable objects found.<br>
+ * {@link #DEBUG_INSTANCES} - Print instance objects.<br>
+ * {@link #DEBUG_OBJECTS} - Print objects other than instances.<br>
+ * {@link #DEBUG_SAVEALL} - Save objects to gc.garbage rather than freeing them.<br>
+ * {@link #DEBUG_LEAK} - Debug leaking programs (everything but STATS).
+ *
+ * @see #DEBUG_STATS
+ * @see #DEBUG_COLLECTABLE
+ * @see #DEBUG_UNCOLLECTABLE
+ * @see #DEBUG_INSTANCES
+ * @see #DEBUG_OBJECTS
+ * @see #DEBUG_SAVEALL
+ * @see #DEBUG_LEAK
+ */
public static void set_debug(int flags) {
debugFlags = flags;
}
+ /**
+ * Copied from CPython-doc:<br>
+ * <br>
+ * Get the garbage collection debugging flags.
+ */
public static int get_debug() {
return debugFlags;
}
+ /**
+ * Not supported by Jython.
+ * Throws {@link org.python.core.Py#NotImplementedError}.
+ *
+ * @throws org.python.core.Py#NotImplementedError
+ */
public static void set_threshold(PyObject[] args, String[] kwargs) {
throw Py.NotImplementedError("not applicable to Java GC");
}
+ /**
+ * Not supported by Jython.
+ * Throws {@link org.python.core.Py#NotImplementedError}.
+ *
+ * @throws org.python.core.Py#NotImplementedError
+ */
public static PyObject get_threshold() {
throw Py.NotImplementedError("not applicable to Java GC");
}
+ /**
+ * Not supported by Jython.
+ * Throws {@link org.python.core.Py#NotImplementedError}.
+ *
+ * @throws org.python.core.Py#NotImplementedError
+ */
public static PyObject get_objects() {
throw Py.NotImplementedError("not applicable to Java GC");
}
@@ -2007,6 +2385,23 @@
return search;
}
+ /**
+ * Does its best to traverse the given {@link org.python.core.PyObject}
+ * {@code ob}. It exploits both
+ * {@link org.python.core.Traverseproc#traverse(Visitproc, Object)} and
+ * {@link org.python.core.TraverseprocDerived#traverseDerived(Visitproc, Object)}.
+ * If {@code ob} neither implements {@link org.python.core.Traverseproc} nor
+ * {@link org.python.core.Traverseproc} and is not annotated with
+ * {@link org.python.core.Untraversable}, reflection-based traversion via
+ * {@link #traverseByReflection(Object, Visitproc, Object)} may be attempted
+ * according to {@link #DONT_TRAVERSE_BY_REFLECTION}.
+ *
+ * @see org.python.core.Traverseproc#traverse(Visitproc, Object)
+ * @see org.python.core.TraverseprocDerived#traverseDerived(Visitproc, Object)
+ * @see #DONT_TRAVERSE_BY_REFLECTION
+ * @see org.python.core.Untraversable
+ * @see #traverseByReflection(Object, Visitproc, Object)
+ */
public static int traverse(PyObject ob, Visitproc visit, Object arg) {
int retVal;
boolean traversed = false;
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list