[Jython-checkins] jython: Fixed issue 2336.

stefan.richthofer jython-checkins at python.org
Tue May 12 18:10:42 CEST 2015


https://hg.python.org/jython/rev/bfa13b3a5553
changeset:   7706:bfa13b3a5553
user:        Stefan Richthofer <stefan.richthofer at gmx.de>
date:        Tue May 12 18:10:07 2015 +0200
summary:
  Fixed issue 2336.

files:
  Lib/test/test_gc_jy.py         |  31 ++++++++++++++-
  src/org/python/modules/gc.java |  45 +++++++++++++++++----
  2 files changed, 64 insertions(+), 12 deletions(-)


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
@@ -14,7 +14,7 @@
 from Queue import Queue
 
 try:
-    from java.lang import System, Runnable
+    from java.lang import System, Runnable, Class
     from javatests import GCTestHelper
 except ImportError:
     #i.e. not Jython is running
@@ -746,9 +746,15 @@
         del prt
         self.assertEqual(gc.collect(), 0)
 
+
+ at unittest.skipUnless(test_support.is_jython,
+        '''
+        The test involves Jython-specifics and is thus not supported by
+        non-Jython interpreters.
+        ''')
 class GCTests_Misc(unittest.TestCase):
 
-    #Test for issue 2337
+    # Test for issue 2337
     def test_queue(self):
         class X(object):
             def __init__(self, q):
@@ -757,6 +763,27 @@
         gc.monitorObject(x)
         gc.collect()
 
+    # Test for issue 2336
+    def test_gc_null(self):
+        WeakReferenceGC = Class.forName('org.python.modules.gc$WeakReferenceGC')
+        # We have to actually construct the right type, the constructor is protected
+        # and Jython doesn't expose that to us; we'd get a plain WeakReference
+        # if we tried WeakReferenceGC()
+        con = WeakReferenceGC.getDeclaredConstructors()[0]
+        con.setAccessible(True)
+        x = object()
+        ref = con.newInstance(x)
+        # It works to start with
+        self.assertTrue(ref == ref)
+        self.assertTrue(ref.get() is x)
+        # Now clean up the referent
+        del x
+        while ref.get():
+            gc.collect()
+        self.assertIsNone(ref.get())
+        # Boom!
+        self.assertTrue(ref == ref)
+
 
 if __name__ == "__main__":
     unittest.main()
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
@@ -641,7 +641,7 @@
     }
 
     private static class WeakReferenceGC extends WeakReference<PyObject> {
-        int hashCode;
+        int hashCode = 0;
         public String str = null, inst_str = null;
         public String cls;
         boolean isInstance;
@@ -705,12 +705,32 @@
         }
 
         public boolean equals(Object ob) {
+            Object ownReferent = get();
             if (ob instanceof WeakReferenceGC) {
-                return ((WeakReferenceGC) ob).get().equals(get())
-                    && ((WeakReferenceGC) ob).hashCode() == hashCode();
+                Object otherReferent = ((WeakReferenceGC) ob).get();
+                if (ownReferent == null || otherReferent == null) {
+                    return ownReferent == otherReferent &&
+                //We compare the cached hash-codes in order to get an idea
+                //whether in the both-null-case the referent was equal once.
+                            hashCode == ((WeakReferenceGC) ob).hashCode;
+                } else {
+                    return otherReferent.equals(ownReferent)
+                //Here the hash-codes are only compared as a consistency check.
+                            && ((WeakReferenceGC) ob).hashCode == hashCode;
+                }
             } else if (ob instanceof WeakrefGCCompareDummy) {
-                return ((WeakrefGCCompareDummy) ob).compare != null
-                        && ((WeakrefGCCompareDummy) ob).compare.equals(get());
+                if (ownReferent == null ||
+                        ((WeakrefGCCompareDummy) ob).compare == null) {
+                    return ownReferent ==
+                            ((WeakrefGCCompareDummy) ob).compare &&
+                //We compare the cached hash-codes in order to get an idea
+                //whether in the both-null-case the referent was equal once.
+                            hashCode == ((WeakrefGCCompareDummy) ob).hashCode;
+                } else {
+                    return ownReferent.equals(((WeakrefGCCompareDummy) ob).compare)
+                //Here the hash-codes are only compared as a consistency check.
+                            && hashCode == ((WeakrefGCCompareDummy) ob).hashCode;
+                }
             } else {
                 return false;
             }
@@ -720,14 +740,19 @@
     private static class WeakrefGCCompareDummy {
         public static WeakrefGCCompareDummy defaultInstance =
                 new WeakrefGCCompareDummy();
-        PyObject compare;
-        int hashCode;
+        protected PyObject compare;
+        int hashCode = 0;
         
         public void setCompare(PyObject compare) {
             this.compare = compare;
             hashCode = System.identityHashCode(compare);
         }
-        
+
+        public void clearCompare() {
+            compare = null;
+            hashCode = 0;
+        }
+
         public int hashCode() {
             return hashCode;
         }
@@ -1430,7 +1455,7 @@
                 WeakrefGCCompareDummy.defaultInstance.setCompare(ob);
                 boolean result = monitoredObjects.contains(
                     WeakrefGCCompareDummy.defaultInstance);
-                WeakrefGCCompareDummy.defaultInstance.compare = null;
+                WeakrefGCCompareDummy.defaultInstance.clearCompare();
                 return result;
             }
         } catch (NullPointerException npe) {
@@ -1448,7 +1473,7 @@
                 }
                 boolean result = monitoredObjects.remove(
                     WeakrefGCCompareDummy.defaultInstance);
-                WeakrefGCCompareDummy.defaultInstance.compare = null;
+                WeakrefGCCompareDummy.defaultInstance.clearCompare();
                 JyAttribute.delAttr(ob, JyAttribute.GC_CYCLE_MARK_ATTR);
                 FinalizeTrigger ft = (FinalizeTrigger)
                     JyAttribute.getAttr(ob, JyAttribute.FINALIZE_TRIGGER_ATTR);

-- 
Repository URL: https://hg.python.org/jython


More information about the Jython-checkins mailing list