On Wed, 24 Jan 2024 05:35:42 GMT, Prasanta Sadhukhan <psadhuk...@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

Reply via email to