Question about weak reference list inside java bridge.

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Question about weak reference list inside java bridge.

Huaidong Qiu
Hi all,

We got a problem like this, one of the L2 entry list keep growing consume
too much memory.

module jurt

package com.sun.star.lib.uno.
environments.java;

the cleanUp member function of class Registry.

        // must only be called while synchronized on map:
        private void cleanUp() {
            for (;;) {
                Level2Entry l2 = (Level2Entry) queue.poll();
                if (l2 == null) {
                    break;
                }
                // It is possible that a Level2Entry e1 for the OID/type
pair
                // (o,t) becomes weakly reachable, then another Level2Entry
e2
                // is registered for the same pair (o,t) (a new Level2Entry
is
                // created since now e1.get() == null), and only then e1 is
                // enqueued.  To not erroneously remove the new e2 in that
case,
                // check whether the map still contains e1:
                String oid = l2.getOid();
                Level1Entry l1 = getLevel1Entry(oid);
                if (l1 != null && l1.get(l2.getType()) == l2) {
                    removeLevel2Entry(oid, l1, l2);
                }
            }
        }

All those weak reference Level2Entry entries are invalid, the condition
(l1.get(l2.getType()) == l2) keeps cleanUp function from removing them from
the list.

I think if this
                // It is possible that a Level2Entry e1 for the OID/type
pair
                // (o,t) becomes weakly reachable, then another Level2Entry
e2
                // is registered for the same pair (o,t) (a new Level2Entry
is
                // created since now e1.get() == null), and only then e1 is
                // enqueued.
happened once then there is no way the condition (l1.get(l2.getType()) ==
l2) can be true again, because get(l2.getType()) always return the first
element in the list, but queue.poll() return the newly released weak
reference which can not be the first one in the list.

If weak reference list cleanup mechanism is correct, could please give some
possible reasons could cause the growing problem of L2 entry list.


Thanks.

Huai Dong
Reply | Threaded
Open this post in threaded view
|

Re: Question about weak reference list inside java bridge.

stephan.bergmann
On 11/23/09 07:58, Huaidong Qiu wrote:

> Hi all,
>
> We got a problem like this, one of the L2 entry list keep growing consume
> too much memory.
>
> module jurt
>
> package com.sun.star.lib.uno.
> environments.java;
>
> the cleanUp member function of class Registry.
>
>         // must only be called while synchronized on map:
>         private void cleanUp() {
>             for (;;) {
>                 Level2Entry l2 = (Level2Entry) queue.poll();
>                 if (l2 == null) {
>                     break;
>                 }
>                 // It is possible that a Level2Entry e1 for the OID/type
> pair
>                 // (o,t) becomes weakly reachable, then another Level2Entry
> e2
>                 // is registered for the same pair (o,t) (a new Level2Entry
> is
>                 // created since now e1.get() == null), and only then e1 is
>                 // enqueued.  To not erroneously remove the new e2 in that
> case,
>                 // check whether the map still contains e1:
>                 String oid = l2.getOid();
>                 Level1Entry l1 = getLevel1Entry(oid);
>                 if (l1 != null && l1.get(l2.getType()) == l2) {
>                     removeLevel2Entry(oid, l1, l2);
>                 }
>             }
>         }
>
> All those weak reference Level2Entry entries are invalid, the condition
> (l1.get(l2.getType()) == l2) keeps cleanUp function from removing them from
> the list.
>
> I think if this
>                 // It is possible that a Level2Entry e1 for the OID/type
> pair
>                 // (o,t) becomes weakly reachable, then another Level2Entry
> e2
>                 // is registered for the same pair (o,t) (a new Level2Entry
> is
>                 // created since now e1.get() == null), and only then e1 is
>                 // enqueued.
> happened once then there is no way the condition (l1.get(l2.getType()) ==
> l2) can be true again, because get(l2.getType()) always return the first
> element in the list, but queue.poll() return the newly released weak
> reference which can not be the first one in the list.

I fail to see a flaw in the current algorithm.  In the simplest case,
consider a Level1Entry L that has just one Level2Entry E (for some
object O, OID D, type T) in its list.  Suppose o1 has become unreachable
and cleanUp is called: l2 will be bound to E; oid will be bound to D; l1
will be bound to L; l2.getType() returns T; l1.get(l2.getType()) returns
E, so removeLevel2Entry will be called and will indeed remove E from L's
list (and will actually also remove L from the map of Level1Entries).

> If weak reference list cleanup mechanism is correct, could please give some
> possible reasons could cause the growing problem of L2 entry list.

You mean, you observe a specific instance of Level1Entry whose list of
Level2Entries keeps growing without bound?  That sounds strange.  First,
all entries in the list should be for different UNO types supported by
the respective UNO object, so that should bound the length of the list
(no UNO object probably supports more than a few dozen different UNO
types).  Second, the only way to have more entries in the list would be
to have entries referencing different reachable Java objects which would
nevertheless all have the same UNO OID.  That would sound like a bug
somewhere.

Maybe you can add debug code to print, for each Level2Entry E in the
list of the given problematic Level1Entry, the following:
- E.toString()
- E.getOid()
- E.getType()
- E.get()
to get an idea what that growing list looks like.

-Stephan

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Question about weak reference list inside java bridge.

Huaidong Qiu
Thanks Stephan,

I already print out the list's contents, the elements's oid and type are
the same,
 but the objects are unreachable.

Same oid because those weak references belong to same L1 entry, no problem
here.

Let's consider  a Level1Entry contains two Level2Entry: l2_1, l2_2.
if l2_1, l2_2 have same type, l1.get(l2.getType())  will return l2_1
because l1.get will return the first element match the type.

            // must only be called while synchronized on map:
            public Level2Entry get(Type type) {
                for (Iterator i = list.iterator(); i.hasNext();) {
                    Level2Entry l2 = (Level2Entry) i.next();
                   * if (l2.getType().equals(type)) {*
                        return l2;
                    }
                }
                return null;
            }

but if when cleanUp was called, the unreachable object is l2_2, the
condition
 (l1.get(l2.getType()) == l2) in cleanUp function will not be met.

I think this is the problem we have, you can see the list will keep growing
after this.

-Huai Dong





On Mon, Nov 23, 2009 at 8:15 PM, Stephan Bergmann
<[hidden email]>wrote:

> On 11/23/09 07:58, Huaidong Qiu wrote:
>
>> Hi all,
>>
>> We got a problem like this, one of the L2 entry list keep growing consume
>> too much memory.
>>
>> module jurt
>>
>> package com.sun.star.lib.uno.
>> environments.java;
>>
>> the cleanUp member function of class Registry.
>>
>>        // must only be called while synchronized on map:
>>        private void cleanUp() {
>>            for (;;) {
>>                Level2Entry l2 = (Level2Entry) queue.poll();
>>                if (l2 == null) {
>>                    break;
>>                }
>>                // It is possible that a Level2Entry e1 for the OID/type
>> pair
>>                // (o,t) becomes weakly reachable, then another Level2Entry
>> e2
>>                // is registered for the same pair (o,t) (a new Level2Entry
>> is
>>                // created since now e1.get() == null), and only then e1 is
>>                // enqueued.  To not erroneously remove the new e2 in that
>> case,
>>                // check whether the map still contains e1:
>>                String oid = l2.getOid();
>>                Level1Entry l1 = getLevel1Entry(oid);
>>                if (l1 != null && l1.get(l2.getType()) == l2) {
>>                    removeLevel2Entry(oid, l1, l2);
>>                }
>>            }
>>        }
>>
>> All those weak reference Level2Entry entries are invalid, the condition
>> (l1.get(l2.getType()) == l2) keeps cleanUp function from removing them
>> from
>> the list.
>>
>> I think if this
>>                // It is possible that a Level2Entry e1 for the OID/type
>> pair
>>                // (o,t) becomes weakly reachable, then another Level2Entry
>> e2
>>                // is registered for the same pair (o,t) (a new Level2Entry
>> is
>>                // created since now e1.get() == null), and only then e1 is
>>                // enqueued.
>> happened once then there is no way the condition (l1.get(l2.getType()) ==
>> l2) can be true again, because get(l2.getType()) always return the first
>> element in the list, but queue.poll() return the newly released weak
>> reference which can not be the first one in the list.
>>
>
> I fail to see a flaw in the current algorithm.  In the simplest case,
> consider a Level1Entry L that has just one Level2Entry E (for some object O,
> OID D, type T) in its list.  Suppose o1 has become unreachable and cleanUp
> is called: l2 will be bound to E; oid will be bound to D; l1 will be bound
> to L; l2.getType() returns T; l1.get(l2.getType()) returns E, so
> removeLevel2Entry will be called and will indeed remove E from L's list (and
> will actually also remove L from the map of Level1Entries).
>
>
>  If weak reference list cleanup mechanism is correct, could please give
>> some
>> possible reasons could cause the growing problem of L2 entry list.
>>
>
> You mean, you observe a specific instance of Level1Entry whose list of
> Level2Entries keeps growing without bound?  That sounds strange.  First, all
> entries in the list should be for different UNO types supported by the
> respective UNO object, so that should bound the length of the list (no UNO
> object probably supports more than a few dozen different UNO types).
>  Second, the only way to have more entries in the list would be to have
> entries referencing different reachable Java objects which would
> nevertheless all have the same UNO OID.  That would sound like a bug
> somewhere.
>
> Maybe you can add debug code to print, for each Level2Entry E in the list
> of the given problematic Level1Entry, the following:
> - E.toString()
> - E.getOid()
> - E.getType()
> - E.get()
> to get an idea what that growing list looks like.
>
> -Stephan
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
Reply | Threaded
Open this post in threaded view
|

Re: Question about weak reference list inside java bridge.

Huaidong Qiu
This is a bad list. I print out

Type,
oid,
o.toString()

The first one is a unreachable object's weak reference, which causes the
growth of list.(not all of them are unreachable, my mistake before)

list start +++++++++
list size: 6
Type[com.sun.star.uno.XCurrentContext]
287d368;msci[0];e64524147b554dde941e6f95d22dc0
null

Type[com.sun.star.uno.XCurrentContext]
287d368;msci[0];e64524147b554dde941e6f95d22dc0
[Proxy:329388962,287d368;msci[0];e64524147b554dde941e6f95d22dc0,Type[com.sun.star.uno.XCurrentContext]]

Type[com.sun.star.uno.XCurrentContext]
287d368;msci[0];e64524147b554dde941e6f95d22dc0
[Proxy:329388962,287d368;msci[0];e64524147b554dde941e6f95d22dc0,Type[com.sun.star.uno.XCurrentContext]]

Type[com.sun.star.uno.XCurrentContext]
287d368;msci[0];e64524147b554dde941e6f95d22dc0
[Proxy:329388962,287d368;msci[0];e64524147b554dde941e6f95d22dc0,Type[com.sun.star.uno.XCurrentContext]]

Type[com.sun.star.uno.XCurrentContext]
287d368;msci[0];e64524147b554dde941e6f95d22dc0
[Proxy:329388962,287d368;msci[0];e64524147b554dde941e6f95d22dc0,Type[com.sun.star.uno.XCurrentContext]]

Type[com.sun.star.uno.XCurrentContext]
287d368;msci[0];e64524147b554dde941e6f95d22dc0
[Proxy:329388962,287d368;msci[0];e64524147b554dde941e6f95d22dc0,Type[com.sun.star.uno.XCurrentContext]]
list end   +++++++++


On Mon, Nov 23, 2009 at 9:32 PM, Huaidong Qiu <[hidden email]> wrote:

> Thanks Stephan,
>
> I already print out the list's contents, the elements's oid and type are
> the same,
>  but the objects are unreachable.
>
> Same oid because those weak references belong to same L1 entry, no problem
> here.
>
> Let's consider  a Level1Entry contains two Level2Entry: l2_1, l2_2.
> if l2_1, l2_2 have same type, l1.get(l2.getType())  will return l2_1
> because l1.get will return the first element match the type.
>
>
>             // must only be called while synchronized on map:
>             public Level2Entry get(Type type) {
>                 for (Iterator i = list.iterator(); i.hasNext();) {
>                     Level2Entry l2 = (Level2Entry) i.next();
>                    * if (l2.getType().equals(type)) {*
>                         return l2;
>                     }
>                 }
>                 return null;
>             }
>
> but if when cleanUp was called, the unreachable object is l2_2, the
> condition
>  (l1.get(l2.getType()) == l2) in cleanUp function will not be met.
>
> I think this is the problem we have, you can see the list will keep growing
> after this.
>
> -Huai Dong
>
>
>
>
>
>
> On Mon, Nov 23, 2009 at 8:15 PM, Stephan Bergmann <
> [hidden email]> wrote:
>
>> On 11/23/09 07:58, Huaidong Qiu wrote:
>>
>>> Hi all,
>>>
>>> We got a problem like this, one of the L2 entry list keep growing consume
>>> too much memory.
>>>
>>> module jurt
>>>
>>> package com.sun.star.lib.uno.
>>> environments.java;
>>>
>>> the cleanUp member function of class Registry.
>>>
>>>        // must only be called while synchronized on map:
>>>        private void cleanUp() {
>>>            for (;;) {
>>>                Level2Entry l2 = (Level2Entry) queue.poll();
>>>                if (l2 == null) {
>>>                    break;
>>>                }
>>>                // It is possible that a Level2Entry e1 for the OID/type
>>> pair
>>>                // (o,t) becomes weakly reachable, then another
>>> Level2Entry
>>> e2
>>>                // is registered for the same pair (o,t) (a new
>>> Level2Entry
>>> is
>>>                // created since now e1.get() == null), and only then e1
>>> is
>>>                // enqueued.  To not erroneously remove the new e2 in that
>>> case,
>>>                // check whether the map still contains e1:
>>>                String oid = l2.getOid();
>>>                Level1Entry l1 = getLevel1Entry(oid);
>>>                if (l1 != null && l1.get(l2.getType()) == l2) {
>>>                    removeLevel2Entry(oid, l1, l2);
>>>                }
>>>            }
>>>        }
>>>
>>> All those weak reference Level2Entry entries are invalid, the condition
>>> (l1.get(l2.getType()) == l2) keeps cleanUp function from removing them
>>> from
>>> the list.
>>>
>>> I think if this
>>>                // It is possible that a Level2Entry e1 for the OID/type
>>> pair
>>>                // (o,t) becomes weakly reachable, then another
>>> Level2Entry
>>> e2
>>>                // is registered for the same pair (o,t) (a new
>>> Level2Entry
>>> is
>>>                // created since now e1.get() == null), and only then e1
>>> is
>>>                // enqueued.
>>> happened once then there is no way the condition (l1.get(l2.getType()) ==
>>> l2) can be true again, because get(l2.getType()) always return the first
>>> element in the list, but queue.poll() return the newly released weak
>>> reference which can not be the first one in the list.
>>>
>>
>> I fail to see a flaw in the current algorithm.  In the simplest case,
>> consider a Level1Entry L that has just one Level2Entry E (for some object O,
>> OID D, type T) in its list.  Suppose o1 has become unreachable and cleanUp
>> is called: l2 will be bound to E; oid will be bound to D; l1 will be bound
>> to L; l2.getType() returns T; l1.get(l2.getType()) returns E, so
>> removeLevel2Entry will be called and will indeed remove E from L's list (and
>> will actually also remove L from the map of Level1Entries).
>>
>>
>>  If weak reference list cleanup mechanism is correct, could please give
>>> some
>>> possible reasons could cause the growing problem of L2 entry list.
>>>
>>
>> You mean, you observe a specific instance of Level1Entry whose list of
>> Level2Entries keeps growing without bound?  That sounds strange.  First, all
>> entries in the list should be for different UNO types supported by the
>> respective UNO object, so that should bound the length of the list (no UNO
>> object probably supports more than a few dozen different UNO types).
>>  Second, the only way to have more entries in the list would be to have
>> entries referencing different reachable Java objects which would
>> nevertheless all have the same UNO OID.  That would sound like a bug
>> somewhere.
>>
>> Maybe you can add debug code to print, for each Level2Entry E in the list
>> of the given problematic Level1Entry, the following:
>> - E.toString()
>> - E.getOid()
>> - E.getType()
>> - E.get()
>> to get an idea what that growing list looks like.
>>
>> -Stephan
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>>
>
Reply | Threaded
Open this post in threaded view
|

Re: Question about weak reference list inside java bridge.

stephan.bergmann
Yes, thanks.  I think now I get it.  The code in cleanUp mistakenly
thinks that Level1Entry.get is backed by a map (where there can be at
most one entry for a given key) while in fact it is backed by a list
(acting like a multi-map, allowing multiple entries for a given key).

I will see how best to fix that tomorrow.  If you like, you can file an
issue (otherwise, I will file one myself).

-Stephan

On 11/23/09 18:15, Huaidong Qiu wrote:

> This is a bad list. I print out
>
> Type,
> oid,
> o.toString()
>
> The first one is a unreachable object's weak reference, which causes the
> growth of list.(not all of them are unreachable, my mistake before)
>
> list start +++++++++
> list size: 6
> Type[com.sun.star.uno.XCurrentContext]
> 287d368;msci[0];e64524147b554dde941e6f95d22dc0
> null
>
> Type[com.sun.star.uno.XCurrentContext]
> 287d368;msci[0];e64524147b554dde941e6f95d22dc0
> [Proxy:329388962,287d368;msci[0];e64524147b554dde941e6f95d22dc0,Type[com.sun.star.uno.XCurrentContext]]
>
> Type[com.sun.star.uno.XCurrentContext]
> 287d368;msci[0];e64524147b554dde941e6f95d22dc0
> [Proxy:329388962,287d368;msci[0];e64524147b554dde941e6f95d22dc0,Type[com.sun.star.uno.XCurrentContext]]
>
> Type[com.sun.star.uno.XCurrentContext]
> 287d368;msci[0];e64524147b554dde941e6f95d22dc0
> [Proxy:329388962,287d368;msci[0];e64524147b554dde941e6f95d22dc0,Type[com.sun.star.uno.XCurrentContext]]
>
> Type[com.sun.star.uno.XCurrentContext]
> 287d368;msci[0];e64524147b554dde941e6f95d22dc0
> [Proxy:329388962,287d368;msci[0];e64524147b554dde941e6f95d22dc0,Type[com.sun.star.uno.XCurrentContext]]
>
> Type[com.sun.star.uno.XCurrentContext]
> 287d368;msci[0];e64524147b554dde941e6f95d22dc0
> [Proxy:329388962,287d368;msci[0];e64524147b554dde941e6f95d22dc0,Type[com.sun.star.uno.XCurrentContext]]
> list end   +++++++++
>
>
> On Mon, Nov 23, 2009 at 9:32 PM, Huaidong Qiu <[hidden email]> wrote:
>
>> Thanks Stephan,
>>
>> I already print out the list's contents, the elements's oid and type are
>> the same,
>>  but the objects are unreachable.
>>
>> Same oid because those weak references belong to same L1 entry, no problem
>> here.
>>
>> Let's consider  a Level1Entry contains two Level2Entry: l2_1, l2_2.
>> if l2_1, l2_2 have same type, l1.get(l2.getType())  will return l2_1
>> because l1.get will return the first element match the type.
>>
>>
>>             // must only be called while synchronized on map:
>>             public Level2Entry get(Type type) {
>>                 for (Iterator i = list.iterator(); i.hasNext();) {
>>                     Level2Entry l2 = (Level2Entry) i.next();
>>                    * if (l2.getType().equals(type)) {*
>>                         return l2;
>>                     }
>>                 }
>>                 return null;
>>             }
>>
>> but if when cleanUp was called, the unreachable object is l2_2, the
>> condition
>>  (l1.get(l2.getType()) == l2) in cleanUp function will not be met.
>>
>> I think this is the problem we have, you can see the list will keep growing
>> after this.
>>
>> -Huai Dong
>>
>>
>>
>>
>>
>>
>> On Mon, Nov 23, 2009 at 8:15 PM, Stephan Bergmann <
>> [hidden email]> wrote:
>>
>>> On 11/23/09 07:58, Huaidong Qiu wrote:
>>>
>>>> Hi all,
>>>>
>>>> We got a problem like this, one of the L2 entry list keep growing consume
>>>> too much memory.
>>>>
>>>> module jurt
>>>>
>>>> package com.sun.star.lib.uno.
>>>> environments.java;
>>>>
>>>> the cleanUp member function of class Registry.
>>>>
>>>>        // must only be called while synchronized on map:
>>>>        private void cleanUp() {
>>>>            for (;;) {
>>>>                Level2Entry l2 = (Level2Entry) queue.poll();
>>>>                if (l2 == null) {
>>>>                    break;
>>>>                }
>>>>                // It is possible that a Level2Entry e1 for the OID/type
>>>> pair
>>>>                // (o,t) becomes weakly reachable, then another
>>>> Level2Entry
>>>> e2
>>>>                // is registered for the same pair (o,t) (a new
>>>> Level2Entry
>>>> is
>>>>                // created since now e1.get() == null), and only then e1
>>>> is
>>>>                // enqueued.  To not erroneously remove the new e2 in that
>>>> case,
>>>>                // check whether the map still contains e1:
>>>>                String oid = l2.getOid();
>>>>                Level1Entry l1 = getLevel1Entry(oid);
>>>>                if (l1 != null && l1.get(l2.getType()) == l2) {
>>>>                    removeLevel2Entry(oid, l1, l2);
>>>>                }
>>>>            }
>>>>        }
>>>>
>>>> All those weak reference Level2Entry entries are invalid, the condition
>>>> (l1.get(l2.getType()) == l2) keeps cleanUp function from removing them
>>>> from
>>>> the list.
>>>>
>>>> I think if this
>>>>                // It is possible that a Level2Entry e1 for the OID/type
>>>> pair
>>>>                // (o,t) becomes weakly reachable, then another
>>>> Level2Entry
>>>> e2
>>>>                // is registered for the same pair (o,t) (a new
>>>> Level2Entry
>>>> is
>>>>                // created since now e1.get() == null), and only then e1
>>>> is
>>>>                // enqueued.
>>>> happened once then there is no way the condition (l1.get(l2.getType()) ==
>>>> l2) can be true again, because get(l2.getType()) always return the first
>>>> element in the list, but queue.poll() return the newly released weak
>>>> reference which can not be the first one in the list.
>>>>
>>> I fail to see a flaw in the current algorithm.  In the simplest case,
>>> consider a Level1Entry L that has just one Level2Entry E (for some object O,
>>> OID D, type T) in its list.  Suppose o1 has become unreachable and cleanUp
>>> is called: l2 will be bound to E; oid will be bound to D; l1 will be bound
>>> to L; l2.getType() returns T; l1.get(l2.getType()) returns E, so
>>> removeLevel2Entry will be called and will indeed remove E from L's list (and
>>> will actually also remove L from the map of Level1Entries).
>>>
>>>
>>>  If weak reference list cleanup mechanism is correct, could please give
>>>> some
>>>> possible reasons could cause the growing problem of L2 entry list.
>>>>
>>> You mean, you observe a specific instance of Level1Entry whose list of
>>> Level2Entries keeps growing without bound?  That sounds strange.  First, all
>>> entries in the list should be for different UNO types supported by the
>>> respective UNO object, so that should bound the length of the list (no UNO
>>> object probably supports more than a few dozen different UNO types).
>>>  Second, the only way to have more entries in the list would be to have
>>> entries referencing different reachable Java objects which would
>>> nevertheless all have the same UNO OID.  That would sound like a bug
>>> somewhere.
>>>
>>> Maybe you can add debug code to print, for each Level2Entry E in the list
>>> of the given problematic Level1Entry, the following:
>>> - E.toString()
>>> - E.getOid()
>>> - E.getType()
>>> - E.get()
>>> to get an idea what that growing list looks like.
>>>
>>> -Stephan

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Question about weak reference list inside java bridge.

Huaidong Qiu
Hi Stephan,

I filed a issue for this problem, ISSUE#
107157<http://www.openoffice.org/issues/show_bug.cgi?id=107157>
.


Thanks for you help



On Tue, Nov 24, 2009 at 1:29 AM, Stephan Bergmann
<[hidden email]>wrote:

> Yes, thanks.  I think now I get it.  The code in cleanUp mistakenly thinks
> that Level1Entry.get is backed by a map (where there can be at most one
> entry for a given key) while in fact it is backed by a list (acting like a
> multi-map, allowing multiple entries for a given key).
>
> I will see how best to fix that tomorrow.  If you like, you can file an
> issue (otherwise, I will file one myself).
>
> -Stephan
>
>
> On 11/23/09 18:15, Huaidong Qiu wrote:
>
>> This is a bad list. I print out
>>
>> Type,
>> oid,
>> o.toString()
>>
>> The first one is a unreachable object's weak reference, which causes the
>> growth of list.(not all of them are unreachable, my mistake before)
>>
>> list start +++++++++
>> list size: 6
>> Type[com.sun.star.uno.XCurrentContext]
>> 287d368;msci[0];e64524147b554dde941e6f95d22dc0
>> null
>>
>> Type[com.sun.star.uno.XCurrentContext]
>> 287d368;msci[0];e64524147b554dde941e6f95d22dc0
>>
>> [Proxy:329388962,287d368;msci[0];e64524147b554dde941e6f95d22dc0,Type[com.sun.star.uno.XCurrentContext]]
>>
>> Type[com.sun.star.uno.XCurrentContext]
>> 287d368;msci[0];e64524147b554dde941e6f95d22dc0
>>
>> [Proxy:329388962,287d368;msci[0];e64524147b554dde941e6f95d22dc0,Type[com.sun.star.uno.XCurrentContext]]
>>
>> Type[com.sun.star.uno.XCurrentContext]
>> 287d368;msci[0];e64524147b554dde941e6f95d22dc0
>>
>> [Proxy:329388962,287d368;msci[0];e64524147b554dde941e6f95d22dc0,Type[com.sun.star.uno.XCurrentContext]]
>>
>> Type[com.sun.star.uno.XCurrentContext]
>> 287d368;msci[0];e64524147b554dde941e6f95d22dc0
>>
>> [Proxy:329388962,287d368;msci[0];e64524147b554dde941e6f95d22dc0,Type[com.sun.star.uno.XCurrentContext]]
>>
>> Type[com.sun.star.uno.XCurrentContext]
>> 287d368;msci[0];e64524147b554dde941e6f95d22dc0
>>
>> [Proxy:329388962,287d368;msci[0];e64524147b554dde941e6f95d22dc0,Type[com.sun.star.uno.XCurrentContext]]
>> list end   +++++++++
>>
>>
>> On Mon, Nov 23, 2009 at 9:32 PM, Huaidong Qiu <[hidden email]>
>> wrote:
>>
>>  Thanks Stephan,
>>>
>>> I already print out the list's contents, the elements's oid and type are
>>> the same,
>>>  but the objects are unreachable.
>>>
>>> Same oid because those weak references belong to same L1 entry, no
>>> problem
>>> here.
>>>
>>> Let's consider  a Level1Entry contains two Level2Entry: l2_1, l2_2.
>>> if l2_1, l2_2 have same type, l1.get(l2.getType())  will return l2_1
>>> because l1.get will return the first element match the type.
>>>
>>>
>>>            // must only be called while synchronized on map:
>>>            public Level2Entry get(Type type) {
>>>                for (Iterator i = list.iterator(); i.hasNext();) {
>>>                    Level2Entry l2 = (Level2Entry) i.next();
>>>                   * if (l2.getType().equals(type)) {*
>>>                        return l2;
>>>                    }
>>>                }
>>>                return null;
>>>            }
>>>
>>> but if when cleanUp was called, the unreachable object is l2_2, the
>>> condition
>>>  (l1.get(l2.getType()) == l2) in cleanUp function will not be met.
>>>
>>> I think this is the problem we have, you can see the list will keep
>>> growing
>>> after this.
>>>
>>> -Huai Dong
>>>
>>>
>>>
>>>
>>>
>>>
>>> On Mon, Nov 23, 2009 at 8:15 PM, Stephan Bergmann <
>>> [hidden email]> wrote:
>>>
>>>  On 11/23/09 07:58, Huaidong Qiu wrote:
>>>>
>>>>  Hi all,
>>>>>
>>>>> We got a problem like this, one of the L2 entry list keep growing
>>>>> consume
>>>>> too much memory.
>>>>>
>>>>> module jurt
>>>>>
>>>>> package com.sun.star.lib.uno.
>>>>> environments.java;
>>>>>
>>>>> the cleanUp member function of class Registry.
>>>>>
>>>>>       // must only be called while synchronized on map:
>>>>>       private void cleanUp() {
>>>>>           for (;;) {
>>>>>               Level2Entry l2 = (Level2Entry) queue.poll();
>>>>>               if (l2 == null) {
>>>>>                   break;
>>>>>               }
>>>>>               // It is possible that a Level2Entry e1 for the OID/type
>>>>> pair
>>>>>               // (o,t) becomes weakly reachable, then another
>>>>> Level2Entry
>>>>> e2
>>>>>               // is registered for the same pair (o,t) (a new
>>>>> Level2Entry
>>>>> is
>>>>>               // created since now e1.get() == null), and only then e1
>>>>> is
>>>>>               // enqueued.  To not erroneously remove the new e2 in
>>>>> that
>>>>> case,
>>>>>               // check whether the map still contains e1:
>>>>>               String oid = l2.getOid();
>>>>>               Level1Entry l1 = getLevel1Entry(oid);
>>>>>               if (l1 != null && l1.get(l2.getType()) == l2) {
>>>>>                   removeLevel2Entry(oid, l1, l2);
>>>>>               }
>>>>>           }
>>>>>       }
>>>>>
>>>>> All those weak reference Level2Entry entries are invalid, the condition
>>>>> (l1.get(l2.getType()) == l2) keeps cleanUp function from removing them
>>>>> from
>>>>> the list.
>>>>>
>>>>> I think if this
>>>>>               // It is possible that a Level2Entry e1 for the OID/type
>>>>> pair
>>>>>               // (o,t) becomes weakly reachable, then another
>>>>> Level2Entry
>>>>> e2
>>>>>               // is registered for the same pair (o,t) (a new
>>>>> Level2Entry
>>>>> is
>>>>>               // created since now e1.get() == null), and only then e1
>>>>> is
>>>>>               // enqueued.
>>>>> happened once then there is no way the condition (l1.get(l2.getType())
>>>>> ==
>>>>> l2) can be true again, because get(l2.getType()) always return the
>>>>> first
>>>>> element in the list, but queue.poll() return the newly released weak
>>>>> reference which can not be the first one in the list.
>>>>>
>>>>>  I fail to see a flaw in the current algorithm.  In the simplest case,
>>>> consider a Level1Entry L that has just one Level2Entry E (for some
>>>> object O,
>>>> OID D, type T) in its list.  Suppose o1 has become unreachable and
>>>> cleanUp
>>>> is called: l2 will be bound to E; oid will be bound to D; l1 will be
>>>> bound
>>>> to L; l2.getType() returns T; l1.get(l2.getType()) returns E, so
>>>> removeLevel2Entry will be called and will indeed remove E from L's list
>>>> (and
>>>> will actually also remove L from the map of Level1Entries).
>>>>
>>>>
>>>>  If weak reference list cleanup mechanism is correct, could please give
>>>>
>>>>> some
>>>>> possible reasons could cause the growing problem of L2 entry list.
>>>>>
>>>>>  You mean, you observe a specific instance of Level1Entry whose list of
>>>> Level2Entries keeps growing without bound?  That sounds strange.  First,
>>>> all
>>>> entries in the list should be for different UNO types supported by the
>>>> respective UNO object, so that should bound the length of the list (no
>>>> UNO
>>>> object probably supports more than a few dozen different UNO types).
>>>>  Second, the only way to have more entries in the list would be to have
>>>> entries referencing different reachable Java objects which would
>>>> nevertheless all have the same UNO OID.  That would sound like a bug
>>>> somewhere.
>>>>
>>>> Maybe you can add debug code to print, for each Level2Entry E in the
>>>> list
>>>> of the given problematic Level1Entry, the following:
>>>> - E.toString()
>>>> - E.getOid()
>>>> - E.getType()
>>>> - E.get()
>>>> to get an idea what that growing list looks like.
>>>>
>>>> -Stephan
>>>>
>>>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>