RFR: 6507038: Memory Leak in JTree / BasicTreeUI [v3]
Alexey Ivanov
aivanov at openjdk.org
Wed Jan 24 20:38:33 UTC 2024
On Wed, 24 Jan 2024 05:35:42 GMT, Prasanta Sadhukhan <psadhukhan at openjdk.org> wrote:
>> When using a TreeCellRenterer which creates new components in getTreeCellRendererComponent() in a JTree that is not visible, changes to the nodes cause a memory leak.
>> When a node is changed, the Method getNodeDimensions() is called to calculate the new dimensions for the node. In this method, getTreeCellRendererComponent() is called to obtain the renderer component (what else...) and [this component is added to rendererPane](https://github.com/openjdk/jdk/blob/36f4b34f1953af736706ec67192204727808bc6c/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java#L3283-L3284). It is not removed from the rendererPane afterwards.
>> Only when the tree is painted, the paint() method does a removeAll on the rendererPane [in this code](https://github.com/openjdk/jdk/blob/36f4b34f1953af736706ec67192204727808bc6c/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java#L1500)
>>
>> FIx is added to remove the components from rendererPane when the JTree UI is changed/uninstalled only when tree is not visible since they are already removed when tree is painted in paint() method..
>
> Prasanta Sadhukhan has updated the pull request incrementally with one additional commit since the last revision:
>
> Retain last component in rendererPane. Testcase added
Changes requested by aivanov (Reviewer).
src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java line 3285:
> 3283: for (int i = 0; i < rendererPane.getComponentCount(); i++) {
> 3284: rendererPane.remove(i);
> 3285: }
rendererPane.removeAll()?
Suggestion:
rendererPane.removeAll();
test/jdk/javax/swing/plaf/basic/BasicTreeUI/TreeCellRendererLeakTest.java line 62:
> 60: }
> 61:
> 62: public void finalize( ) {
The `finalize` method is deprecated. Can't we use `Reference` API for this purpose?
Store a list of [`PhantomReference<JLabel>`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/ref/PhantomReference.html). The size of the list is the number of `JLabel` objects created. Once you receive a reference via the [`ReferenceQueue`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/ref/ReferenceQueue.html), remove it from the list.
test/jdk/javax/swing/plaf/basic/BasicTreeUI/TreeCellRendererLeakTest.java line 90:
> 88: }
> 89:
> 90: return label;
Here, before returning the `label` object, create a `PhantomReference` and add it to a list of references.
test/jdk/javax/swing/plaf/basic/BasicTreeUI/TreeCellRendererLeakTest.java line 101:
> 99: runChanges( );
> 100: }
> 101: });
This could be a method reference:
Suggestion:
Thread updateThread = new Thread(this::runChanges);
test/jdk/javax/swing/plaf/basic/BasicTreeUI/TreeCellRendererLeakTest.java line 108:
> 106: runInfo( );
> 107: }
> 108: });
Suggestion:
Thread infoThread = new Thread(this::runInfo);
test/jdk/javax/swing/plaf/basic/BasicTreeUI/TreeCellRendererLeakTest.java line 150:
> 148: while (!done) {
> 149: Thread.sleep(100);
> 150: }
Can't we use [`CountDownLatch`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/CountDownLatch.html) instead of a boolean flag and busy-waiting?
test/jdk/javax/swing/plaf/basic/BasicTreeUI/TreeCellRendererLeakTest.java line 183:
> 181: } catch (Exception ex) {
> 182: ex.printStackTrace();
> 183: }
You may want to handle `InterruptedException` by exiting from the thread…
test/jdk/javax/swing/plaf/basic/BasicTreeUI/TreeCellRendererLeakTest.java line 191:
> 189: public void runInfo( ) {
> 190: long time = System.currentTimeMillis();
> 191: long initialCnt = smCount;
Access to `smCount` or a list of references need to be synchronised.
-------------
PR Review: https://git.openjdk.org/jdk/pull/17458#pullrequestreview-1842292468
PR Review Comment: https://git.openjdk.org/jdk/pull/17458#discussion_r1465491797
PR Review Comment: https://git.openjdk.org/jdk/pull/17458#discussion_r1465498201
PR Review Comment: https://git.openjdk.org/jdk/pull/17458#discussion_r1465504463
PR Review Comment: https://git.openjdk.org/jdk/pull/17458#discussion_r1465505654
PR Review Comment: https://git.openjdk.org/jdk/pull/17458#discussion_r1465506021
PR Review Comment: https://git.openjdk.org/jdk/pull/17458#discussion_r1465499294
PR Review Comment: https://git.openjdk.org/jdk/pull/17458#discussion_r1465507807
PR Review Comment: https://git.openjdk.org/jdk/pull/17458#discussion_r1465501423
More information about the client-libs-dev
mailing list