You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Thomas Neidhart <th...@gmail.com> on 2013/03/07 23:09:02 UTC

[logging] IBM JDK and ReferenceQueue

Hi,

I have installed the following JDK on my machine:

java version "1.6.0"
Java(TM) SE Runtime Environment (build pxi3260sr12-20121025_01(SR12))
IBM J9 VM (build 2.4, JRE 1.6.0 IBM J9 2.4 Linux x86-32
jvmxi3260sr12-20121024_126067 (JIT enabled, AOT enabled)
J9VM - 20121024_126067
JIT  - r9_20120914_26057
GC   - 20120928_AA)
JCL  - 20121014_01

When I try to run the following test from the IBM developerworks wrt
WeakReferences and ReferenceQueue, the reference is never put on the
reference queue (the problem that I also had in the WeakHashtable testcase):

url: http://www.ibm.com/developerworks/library/j-refs/

output:

Example of incorrectly holding a strong reference
object is MyObject@3b203b2
The weak reference is java.lang.ref.WeakReference@46d046d
Polling the reference queue returns null
Getting the referent from the weak reference returns MyObject@3b203b2
Calling GC
Polling the reference queue returns null
Getting the referent from the weak reference returns null

Example of correctly releasing a strong reference
object is MyObject@2bd62bd6
The weak reference is java.lang.ref.WeakReference@37c637c6
Polling the reference queue returns null
Getting the referent from the weak reference returns MyObject@2bd62bd6
Set the obj reference to null and call GC
Polling the reference queue returns null
Getting the referent from the weak reference returns null
In finalize method for this object: MyObject@3b203b2
In finalize method for this object: MyObject@2bd62bd6


Polling the reference queue always returns null, even when the
WeakReference has lost its referent.

Can somebody confirm this?

Thanks,

Thomas

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Re: [logging] IBM JDK and ReferenceQueue

Posted by Thomas Neidhart <th...@gmail.com>.
On 03/07/2013 11:09 PM, Thomas Neidhart wrote:
> Hi,
> 
> I have installed the following JDK on my machine:
> 
> java version "1.6.0"
> Java(TM) SE Runtime Environment (build pxi3260sr12-20121025_01(SR12))
> IBM J9 VM (build 2.4, JRE 1.6.0 IBM J9 2.4 Linux x86-32
> jvmxi3260sr12-20121024_126067 (JIT enabled, AOT enabled)
> J9VM - 20121024_126067
> JIT  - r9_20120914_26057
> GC   - 20120928_AA)
> JCL  - 20121014_01
> 
> When I try to run the following test from the IBM developerworks wrt
> WeakReferences and ReferenceQueue, the reference is never put on the
> reference queue (the problem that I also had in the WeakHashtable testcase):
> 
> url: http://www.ibm.com/developerworks/library/j-refs/
> 
> output:
> 
> Example of incorrectly holding a strong reference
> object is MyObject@3b203b2
> The weak reference is java.lang.ref.WeakReference@46d046d
> Polling the reference queue returns null
> Getting the referent from the weak reference returns MyObject@3b203b2
> Calling GC
> Polling the reference queue returns null
> Getting the referent from the weak reference returns null
> 
> Example of correctly releasing a strong reference
> object is MyObject@2bd62bd6
> The weak reference is java.lang.ref.WeakReference@37c637c6
> Polling the reference queue returns null
> Getting the referent from the weak reference returns MyObject@2bd62bd6
> Set the obj reference to null and call GC
> Polling the reference queue returns null
> Getting the referent from the weak reference returns null
> In finalize method for this object: MyObject@3b203b2
> In finalize method for this object: MyObject@2bd62bd6
> 
> 
> Polling the reference queue always returns null, even when the
> WeakReference has lost its referent.
> 
> Can somebody confirm this?

Another weird thing:

Consider this testcase:

    public static void main (String[] args) {
        Object obj = new Object();
        ReferenceQueue queue = new ReferenceQueue();
        Reference ref = new WeakReference(obj, queue);

        obj = null;
        System.gc();

// first approach

        Reference ref1 = null;
        while ( (ref1 = queue.poll()) == null ) {
            System.out.println(ref1);
        }
        System.out.println(ref1);

// second approach
//        Reference ref1 = null;
//        do {
//            ref1 = queue.poll();
//            System.out.println("Polling the reference queue returns " +
//                           ref);
//        } while (ref == null);
    }

The first one results in an endless loop of null outputs
The second one returns immediately an reference

This with IBM JDK 6. With OpenJDK 6 I get the same result with both
approaches.

Thomas

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Re: [logging] IBM JDK and ReferenceQueue

Posted by Jörg Schaible <jo...@gmx.de>.
Hi Thomas,

Thomas Neidhart wrote:

[snip]

> Anyway, the logic in WeakHashtable is flawed, as it relies on the queue
> to purge elements from the table. When considering for example the
> elements method:
> 
>     public Enumeration elements() {
>         purge();
>         return super.elements();
>     }
> 
> This purges any elements whose key is put into the queue and then
> delegates to super.elements. When a key that has already been gc'ed
> (Reference.getKey == null), but not yet been put on the queue, the
> corresponding WeakKey is still contained in the map, and thus,
> super.elements() will return this element.
> 
> Other methods like keySet also check if the referent of the
> WeakReference is null and omit such entries from the reply, thus leading
> to different results, leading to different results than e.g. size().
> 
> In logging, there are 5 methods from WeakHashtable used:
> 
>  * get
>  * put
>  * remove
>  * elements
>  * clear
> 
> The only problematic one being elements, and it is used to release all
> registered factories, so this should be safe imho.
> 
> We could change the purge method to not rely on the queue, but always
> iterate over the entrySet and remove the entries whose referent key is
> null and update the testcase to ignore the queue?

The implementation does the right thing using the queue. IMHO are all the 
tests problematic that try to force the GC, because they make (invalid) 
assumptions about the GC strategy of the JDK.

- Jörg


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Re: [logging] IBM JDK and ReferenceQueue

Posted by Thomas Neidhart <th...@gmail.com>.
On 03/07/2013 11:09 PM, Thomas Neidhart wrote:
> Hi,
> 
> I have installed the following JDK on my machine:
> 
> java version "1.6.0"
> Java(TM) SE Runtime Environment (build pxi3260sr12-20121025_01(SR12))
> IBM J9 VM (build 2.4, JRE 1.6.0 IBM J9 2.4 Linux x86-32
> jvmxi3260sr12-20121024_126067 (JIT enabled, AOT enabled)
> J9VM - 20121024_126067
> JIT  - r9_20120914_26057
> GC   - 20120928_AA)
> JCL  - 20121014_01
> 
> When I try to run the following test from the IBM developerworks wrt
> WeakReferences and ReferenceQueue, the reference is never put on the
> reference queue (the problem that I also had in the WeakHashtable testcase):
> 
> url: http://www.ibm.com/developerworks/library/j-refs/
> 
> output:
> 
> Example of incorrectly holding a strong reference
> object is MyObject@3b203b2
> The weak reference is java.lang.ref.WeakReference@46d046d
> Polling the reference queue returns null
> Getting the referent from the weak reference returns MyObject@3b203b2
> Calling GC
> Polling the reference queue returns null
> Getting the referent from the weak reference returns null
> 
> Example of correctly releasing a strong reference
> object is MyObject@2bd62bd6
> The weak reference is java.lang.ref.WeakReference@37c637c6
> Polling the reference queue returns null
> Getting the referent from the weak reference returns MyObject@2bd62bd6
> Set the obj reference to null and call GC
> Polling the reference queue returns null
> Getting the referent from the weak reference returns null
> In finalize method for this object: MyObject@3b203b2
> In finalize method for this object: MyObject@2bd62bd6
> 
> 
> Polling the reference queue always returns null, even when the
> WeakReference has lost its referent.
> 
> Can somebody confirm this?

Obviously the IBM JDK does put released references much later on the
reference queue than the Sun/Oracle/OpenJDK one.

In the testcase from above, it takes some time (replace the queue.poll
with a while and after ~ 10/20 iterations it is on the queue).

I still do not know why in the WeakHashtable test case it is not put on
the queue even after several minutes.

Anyway, the logic in WeakHashtable is flawed, as it relies on the queue
to purge elements from the table. When considering for example the
elements method:

    public Enumeration elements() {
        purge();
        return super.elements();
    }

This purges any elements whose key is put into the queue and then
delegates to super.elements. When a key that has already been gc'ed
(Reference.getKey == null), but not yet been put on the queue, the
corresponding WeakKey is still contained in the map, and thus,
super.elements() will return this element.

Other methods like keySet also check if the referent of the
WeakReference is null and omit such entries from the reply, thus leading
to different results, leading to different results than e.g. size().

In logging, there are 5 methods from WeakHashtable used:

 * get
 * put
 * remove
 * elements
 * clear

The only problematic one being elements, and it is used to release all
registered factories, so this should be safe imho.

We could change the purge method to not rely on the queue, but always
iterate over the entrySet and remove the entries whose referent key is
null and update the testcase to ignore the queue?

Thomas

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Re: [logging] IBM JDK and ReferenceQueue

Posted by Jörg Schaible <jo...@gmx.de>.
Hi Thomas,

Thomas Neidhart wrote:

> Hi,
> 
> I have installed the following JDK on my machine:
> 
> java version "1.6.0"
> Java(TM) SE Runtime Environment (build pxi3260sr12-20121025_01(SR12))
> IBM J9 VM (build 2.4, JRE 1.6.0 IBM J9 2.4 Linux x86-32
> jvmxi3260sr12-20121024_126067 (JIT enabled, AOT enabled)
> J9VM - 20121024_126067
> JIT  - r9_20120914_26057
> GC   - 20120928_AA)
> JCL  - 20121014_01
> 
> When I try to run the following test from the IBM developerworks wrt
> WeakReferences and ReferenceQueue, the reference is never put on the
> reference queue (the problem that I also had in the WeakHashtable
> testcase):
> 
> url: http://www.ibm.com/developerworks/library/j-refs/
> 
> output:
> 
> Example of incorrectly holding a strong reference
> object is MyObject@3b203b2
> The weak reference is java.lang.ref.WeakReference@46d046d
> Polling the reference queue returns null
> Getting the referent from the weak reference returns MyObject@3b203b2
> Calling GC
> Polling the reference queue returns null
> Getting the referent from the weak reference returns null
> 
> Example of correctly releasing a strong reference
> object is MyObject@2bd62bd6
> The weak reference is java.lang.ref.WeakReference@37c637c6
> Polling the reference queue returns null
> Getting the referent from the weak reference returns MyObject@2bd62bd6
> Set the obj reference to null and call GC
> Polling the reference queue returns null
> Getting the referent from the weak reference returns null
> In finalize method for this object: MyObject@3b203b2
> In finalize method for this object: MyObject@2bd62bd6
> 
> 
> Polling the reference queue always returns null, even when the
> WeakReference has lost its referent.
> 
> Can somebody confirm this?

IMHO the test is incorrect. I remember another article about the GC and it 
was stated, that the GC cannot garbage collect objects with a finalizer 
method immediately. It will keep such objects in a special area and return 
them to the queue at its next run when the finalizer has been finished (and 
therefore it is counter-productive to implement that method). That article 
might have been explained GC strategies of newer JDKs (6/7) while this IBM 
article is ancient. With the original test I face a 50% chance that the 
finalizer method runs after polling the queue. IMHO you should modify the 
test to call the GC twice in a row to get proper results for modern GCs. At 
least then I have the expected effect for my IBM 4/5/6 JDKs (amd64-64). 

Funny enough it does not work for my Oracle JDK 7, actually you cannot rely 
at all to System.gc() calls, because you have no idea about the JDKs GC 
strategy. ;-)

- Jörg


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org