Hi.
[Finn]
>Luckily <wink> it happens fairly often on my 300Mhz win2k & jdk1.3.
>
>The situation where it happens for me, seems to be because
>PyJavaClass(__builtin__) gets booted from the internal tables.
>When that happens, all the assignments done in Py.setBuiltinExceptions()
>is lost. The booting is done during PySystemState.initPackages, which is
>before the default PySystemState instance is create. When that instance
>is created, it will keep the __builtin__ dict alive.
>
>Storing a reference of the PyJavaClass(__builtin__) in Py appears to
>close the hole.
>
> private static PyJavaClass v;
>
> public static void setBuiltinExceptions() {
> v = PyJavaClass.lookup(org.python.core.__builtin__.class);
> PyObject dict = v.__getattr__("__dict__");
>
>
>Since the the builtin exceptions are stored in PyJavaClass.__dict__,
>these bindings are not recreated when the PyJavaClass(__builtin__) is
>recreated.
>
>I think that could explain it. Do you agree Samuele?
Yes, if an instance of PyJavaClass is kept alive in the non-weak case just by
the internal tables, it could
be garbage collected when weak internal tables are turned on.
The fix seems fine up to the field name v <wink>.
We should check if something similar is happening for other classes too. I
regret not having done such a check before.
[Rich]
> Also, it seems that the PyBeanEventProperty class is has a memory
> leak. Previously I had made a local patch to it, replacing it's
> HashMap's with WeakHasMaps. I verified that garbage collection was
> occurring by means of debugging print statements in the "finalize" method
> of some of my Java base classes. These same statements are never
> executed when using the new weak reference implementation.
>
> I can't see anything wrong with the new code, but it seems
> fairly certain that it isn't working When I switch back to my
> "WeakHashMap" patch I see that they are executed.
>
> Of course, it's difficult to _prove_ anything here, since I don't have
> much control over when garbage collection occurs. But things do look
> a bit suspicious. Has anyone else been trying out the weak reference
> implementation?
Are the adapters that do not get garbage collected (this should work also
without the weak option,
under java2 the adapters table is always implemented as a WeakHashTable)
or the adaptersClasses?
At least for adapters the following example shows that (at least in principle)
they are garbage collected:
Note: itd.py is the module that I used to debug the new internal tables,
you can use it to track the problem (that would be nice <wink>).
(I already tried that before submitting the new table design).
I have experience that also classes (not tried for adaptersClasses) in the main
table get properly discarded.
Jython 2.0beta2 on java1.3.0 (JIT: null)
Type "copyright", "credits" or "license" for more information.
>>> from java import awt,lang
>>> import itd
>>> itd.ac() # lists the "listeners" for which an adapter-class exists and is
hold in the tbl
[]
>>> itd.ad() # lists the adpter instances (truly the for each one the
"listener"
name is shown)
[]
>>> b=awt.Button() # this alone does not create an adapter
>>> # we force the creation of an adapter
>>> b.actionPerformed
<CompoundCallable with 0 callables>
>>> itd.ac(),itd.ad()
(['java.awt.event.ActionListener'], ['java.awt.event.ActionListener'])
>>> del b
>>> lang.System.gc() # we force gc
>>> itd.ac(),itd.ad() # the adapter should have been gced
(['java.awt.event.ActionListener'], [])
Let me know.
regards, Samuele Pedroni.
<itd.py>
# Copyright 2000 Samuele Pedroni
from java.lang import Class
from org.python.core import PyJavaClass as JC
t=JC.getInternalTables()
def lazy():
r = []
t._beginLazyCanonical()
while 1:
x=t._next()
if not x: break
r.append(x.name)
return r
def canon():
r = []
t._beginCanonical()
while 1:
x=t._next()
if not x: break
r.append(Class.getName(x))
return r
def ac():
r = []
t._beginOverAdapterClasses()
while 1:
x=t._next()
if not x: break
r.append(Class.getName(x))
return r
def ad():
r = []
t._beginOverAdapters()
while 1:
x=t._next()
if not x: break
r.append(Class.getName(x))
return r
|