The Source for Java Technology Collaboration

Home » java.net Forums » Java Desktop Technologies » Swing & AWT

Thread: Removed finalize() in java.awt.Window in Java SE 6

Welcome, Guest Help
Login Login
Guest Settings Guest Settings
Reply to this Thread Reply to this Thread Search Forum Search Forum Back to Thread List Back to Thread List

Permlink Replies: 10 - Last Post: Oct 13, 2008 2:43 AM by: Artem Ananiev
wwwizard

Posts: 10
Removed finalize() in java.awt.Window in Java SE 6
Posted: Oct 8, 2008 9:21 AM
  Click to reply to this thread Reply

I initially posted this in the Java SE Forum, but it's probably more appropriate here. Sorry for the cross post.

http://forums.java.net/jive/thread.jspa?threadID=48471&tstart=0

This is more a question for the AWT/Swing Engineers, but I'm putting it out to the community.

Is there a reason why the finalize() method was removed from java.awt.Window? Was the finalize() causing any dead-locks?

Currently in Java SE 6, without the finalize() method, there is a memory leak when child windows are created. More specifically, a child Window is added to an ownedWindowList Vector of the parent Window, but is never removed (Child windows used to be removed in the finalize()).

I've searched the bug parade, but didn't find any bugs about this mem leak.

wwwizard

Posts: 10
Re: Removed finalize() in java.awt.Window in Java SE 6
Posted: Oct 8, 2008 9:56 AM   in response to: wwwizard
  Click to reply to this thread Reply

I got a NullPointerException while posting so I posted a second time. Marking this one as answered.

Artem Ananiev
Re: Removed finalize() in java.awt.Window in Java SE 6
Posted: Oct 9, 2008 12:51 AM   in response to: wwwizard
  Click to reply to this thread Reply


swing@javadesktop.org wrote:
> I initially posted this in the Java SE Forum, but it's probably more appropriate here. Sorry for the cross post.
>
> http://forums.java.net/jive/thread.jspa?threadID=48471&tstart=0
>
> This is more a question for the AWT/Swing Engineers, but I'm putting it out to the community.
>
> Is there a reason why the finalize() method was removed from java.awt.Window? Was the finalize() causing any dead-locks?

finalize() method is removed as an unreliable way to free resources.
Instead, we use Java2D Disposer machinery which is based on
ReferenceQueue notifications. See java.lang.ref.ReferenceQueue JavaDoc
for details.

> Currently in Java SE 6, without the finalize() method, there is a memory leak when child windows are created. More specifically, a child Window is added to an ownedWindowList Vector of the parent Window, but is never removed (Child windows used to be removed in the finalize()).

The leak looks strange, because only WeakReferences are stored for child
windows, and these references can be freed by GC at any time. Could you
provide a short test which can be used to reproduce the leak?

Thanks,

Artem

> I've searched the bug parade, but didn't find any bugs about this mem leak.
> [Message sent by forum member 'wwwizard' (wwwizard)]
>
> http://forums.java.net/jive/thread.jspa?messageID=304002


wwwizard

Posts: 10
Re: Removed finalize() in java.awt.Window in Java SE 6
Posted: Oct 9, 2008 5:35 AM   in response to: Artem Ananiev
  Click to reply to this thread Reply

When the app is run, the count of WeakReferences that don't have a referent will continually increase.

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Label;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.Enumeration;
import java.util.Vector;
 
/**
 * The following Frame App has two Windows. Clicking on the buttons toggle
 * between the two windows. Each time a Window is set visible, it creates 100
 * child windows. When the other window is hidden, it disposes all its child
 * windows. Using reflection, the app counts the total number of WeakReferences
 * in the Window.ownedWindowList Vector, displaying the total counts of child
 * windows created, the total number of WeakReferences that contain null
 * references, and the total number of WeakReferences that refer to a child
 * Window.
 */
public class MainFrame extends Frame {
 
    Window parentWindow1 = new ParentWindow(this, 1);
    Window parentWindow2 = new ParentWindow(this, 2);
 
    public MainFrame() {
        super("Mem Leak Test1");
 
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent evt) {
                dispose();
            }
        });
 
        parentWindow1.setVisible(true);
    }
 
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MainFrame().setVisible(true);
            }
        });
    }
}
 
class ParentWindow extends Window {
 
    private static final int NUM_WINS   = 100;
    private static final int NULL_INDEX =   0;
    private static final int WEAK_INDEX =   1;
 
    private static int numChildWindowsCreated;
 
    private Window[] childWindows;
 
    public ParentWindow(Window owner, int num) {
        super(owner);
 
        Button button = new Button("Click");
 
        add(new Label("Window " + num), BorderLayout.NORTH);
        add(button);
 
        button.addActionListener(new ClickAction());
 
        pack();
    }
 
    public void setVisible(boolean b) {
        super.setVisible(b);
 
        if (b) {
            createWindows();
        } else {
            disposeWindows();
        }
    }
 
    private void createWindows() {
        childWindows = new Window[NUM_WINS];
 
        for (int i = 0; i < childWindows.length; i++) {
            childWindows[i] = new Window(this);
            numChildWindowsCreated++;
        }
    }
 
    private void disposeWindows() {
    	for (int i = 0; i < childWindows.length; i++) {
            childWindows[i].dispose();
            childWindows[i] = null;
    	}
 
        childWindows = null;
    }
 
    private class ClickAction implements ActionListener {
 
        public void actionPerformed(ActionEvent evt) {
            MainFrame owner = (MainFrame) getOwner();
 
            Window other = (ParentWindow.this == owner.parentWindow1)
                    ? owner.parentWindow2 : owner.parentWindow1;
 
            setVisible(false);
            other.setVisible(true);
 
            int[] counts = new int[2];
 
            countOwnedWindows(owner.parentWindow1, counts);
            countOwnedWindows(owner.parentWindow2, counts);
 
            System.out.println("*********************************");
            System.out.println("Win  Count: " + numChildWindowsCreated);
            System.out.println("Null Count: " + counts[NULL_INDEX]);
            System.out.println("Weak Count: " + counts[WEAK_INDEX]);
        }
 
        private void countOwnedWindows(Window window, int[] counts) {
            try {
                Field field = Window.class.getDeclaredField("ownedWindowList");
                field.setAccessible(true);
                
                Vector vector = (Vector) field.get(window);
                
                Enumeration e = vector.elements();
                
                while (e.hasMoreElements()) {
                    WeakReference ref = (WeakReference) e.nextElement();
                    
                    if (ref.get() == null) {
                        counts[NULL_INDEX]++;
                    } else {
                        counts[WEAK_INDEX]++;
                    }
                }
            //IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException
            } catch (Exception ex) {
                ex.printStackTrace();
                System.exit(0);
            }
        }
    }
}

Sample output:
*********************************
Win  Count: 200
Null Count: 0
Weak Count: 200
*********************************
Win  Count: 300
Null Count: 0
Weak Count: 300
*********************************
Win  Count: 400
Null Count: 0
Weak Count: 400
*********************************
Win  Count: 500
Null Count: 0
Weak Count: 500
*********************************
Win  Count: 600
Null Count: 0
Weak Count: 600
*********************************
Win  Count: 700
Null Count: 0
Weak Count: 700
*********************************
Win  Count: 800
Null Count: 579
Weak Count: 221
*********************************
Win  Count: 900
Null Count: 579
Weak Count: 321
*********************************
Win  Count: 1000
Null Count: 579
Weak Count: 421
*********************************
Win  Count: 1100
Null Count: 579
Weak Count: 521
*********************************
Win  Count: 1200
Null Count: 579
Weak Count: 621
*********************************
Win  Count: 1300
Null Count: 579
Weak Count: 721
*********************************
Win  Count: 1400
Null Count: 1176
Weak Count: 224
*********************************
Win  Count: 1500
Null Count: 1176
Weak Count: 324
*********************************
Win  Count: 1600
Null Count: 1176
Weak Count: 424
*********************************
Win  Count: 1700
Null Count: 1176
Weak Count: 524
*********************************
Win  Count: 1800
Null Count: 1176
Weak Count: 624
*********************************
Win  Count: 1900
Null Count: 1176
Weak Count: 724
*********************************
Win  Count: 2000
Null Count: 1756
Weak Count: 244
*********************************
Win  Count: 2100
Null Count: 1756
Weak Count: 344
*********************************
Win  Count: 2200
Null Count: 1756
Weak Count: 444
*********************************
Win  Count: 2300
Null Count: 1756
Weak Count: 544
*********************************
Win  Count: 2400
Null Count: 1756
Weak Count: 644
*********************************
Win  Count: 2500
Null Count: 1756
Weak Count: 744
*********************************
Win  Count: 2600
Null Count: 2292
Weak Count: 308
*********************************
Win  Count: 2700
Null Count: 2292
Weak Count: 408
*********************************
Win  Count: 2800
Null Count: 2292
Weak Count: 508
*********************************
Win  Count: 2900
Null Count: 2292
Weak Count: 608
*********************************
Win  Count: 3000
Null Count: 2292
Weak Count: 708
*********************************
Win  Count: 3100
Null Count: 2792
Weak Count: 308
*********************************
Win  Count: 3200
Null Count: 2792
Weak Count: 408
*********************************
Win  Count: 3300
Null Count: 2792
Weak Count: 508
*********************************
Win  Count: 3400
Null Count: 2792
Weak Count: 608
*********************************
Win  Count: 3500
Null Count: 2792
Weak Count: 708
*********************************
Win  Count: 3600
Null Count: 2792
Weak Count: 808
*********************************
Win  Count: 3700
Null Count: 2997
Weak Count: 703
*********************************
Win  Count: 3800
Null Count: 2997
Weak Count: 803
*********************************
Win  Count: 3900
Null Count: 2997
Weak Count: 903
*********************************
Win  Count: 4000
Null Count: 2997
Weak Count: 1003
*********************************
Win  Count: 4100
Null Count: 2997
Weak Count: 1103
*********************************
Win  Count: 4200
Null Count: 2997
Weak Count: 1203
*********************************
Win  Count: 4300
Null Count: 3509
Weak Count: 791
*********************************
Win  Count: 4400
Null Count: 3509
Weak Count: 891
*********************************
Win  Count: 4500
Null Count: 3509
Weak Count: 991
*********************************
Win  Count: 4600
Null Count: 3509
Weak Count: 1091
*********************************
Win  Count: 4700
Null Count: 3509
Weak Count: 1191
*********************************
Win  Count: 4800
Null Count: 4009
Weak Count: 791
*********************************
Win  Count: 4900
Null Count: 4009
Weak Count: 891
*********************************
Win  Count: 5000
Null Count: 4009
Weak Count: 991
*********************************
Win  Count: 5100
Null Count: 4009
Weak Count: 1091
*********************************
Win  Count: 5200
Null Count: 4009
Weak Count: 1191
*********************************
Win  Count: 5300
Null Count: 4009
Weak Count: 1291
*********************************
Win  Count: 5400
Null Count: 4371
Weak Count: 1029
*********************************
Win  Count: 5500
Null Count: 4371
Weak Count: 1129
*********************************
Win  Count: 5600
Null Count: 4371
Weak Count: 1229
*********************************
Win  Count: 5700
Null Count: 4371
Weak Count: 1329
*********************************
Win  Count: 5800
Null Count: 4371
Weak Count: 1429
*********************************
Win  Count: 5900
Null Count: 4871
Weak Count: 1029
*********************************
Win  Count: 6000
Null Count: 4871
Weak Count: 1129
*********************************
Win  Count: 6100
Null Count: 4871
Weak Count: 1229
*********************************
Win  Count: 6200
Null Count: 4871
Weak Count: 1329
*********************************
Win  Count: 6300
Null Count: 4871
Weak Count: 1429
*********************************
Win  Count: 6400
Null Count: 4871
Weak Count: 1529
*********************************
Win  Count: 6500
Null Count: 5362
Weak Count: 1138
*********************************
Win  Count: 6600
Null Count: 5362
Weak Count: 1238
*********************************
Win  Count: 6700
Null Count: 5362
Weak Count: 1338
*********************************
Win  Count: 6800
Null Count: 5362
Weak Count: 1438
*********************************
Win  Count: 6900
Null Count: 5362
Weak Count: 1538
*********************************
Win  Count: 7000
Null Count: 5855
Weak Count: 1145
*********************************
Win  Count: 7100
Null Count: 5855
Weak Count: 1245
*********************************
Win  Count: 7200
Null Count: 5855
Weak Count: 1345
*********************************
Win  Count: 7300
Null Count: 5855
Weak Count: 1445
*********************************
Win  Count: 7400
Null Count: 5855
Weak Count: 1545
*********************************
Win  Count: 7500
Null Count: 6355
Weak Count: 1145
*********************************
Win  Count: 7600
Null Count: 6355
Weak Count: 1245
*********************************
Win  Count: 7700
Null Count: 6355
Weak Count: 1345
*********************************
Win  Count: 7800
Null Count: 6355
Weak Count: 1445
*********************************
Win  Count: 7900
Null Count: 6355
Weak Count: 1545
*********************************
Win  Count: 8000
Null Count: 6355
Weak Count: 1645
*********************************
Win  Count: 8100
Null Count: 6816
Weak Count: 1284
*********************************
Win  Count: 8200
Null Count: 6816
Weak Count: 1384
*********************************
Win  Count: 8300
Null Count: 6816
Weak Count: 1484
*********************************
Win  Count: 8400
Null Count: 6816
Weak Count: 1584


Artem Ananiev
Re: Removed finalize() in java.awt.Window in Java SE 6
Posted: Oct 9, 2008 5:44 AM   in response to: wwwizard
  Click to reply to this thread Reply


swing@javadesktop.org wrote:
> When the app is run, the count of WeakReferences that don't have a referent will continually increase.

This doesn't mean a leak. Try the following simple scenario:

1. Create an instance of class which is suspected to leak (child window)
2. Make a weak reference to this instance, and remove all the strong
references
3. Consume all the available heap (for example, by allocating byte
arrays in a loop and storing them in a Vector)
4. Check the value of your weak reference. If it is not null, then some
other code (AWT) holds a strong reference to the same object.

Thanks,

Artem

>
> import java.awt.BorderLayout;
> import java.awt.Button;
> import java.awt.EventQueue;
> import java.awt.Frame;
> import java.awt.Label;
> import java.awt.Window;
> import java.awt.event.ActionEvent;
> import java.awt.event.ActionListener;
> import java.awt.event.WindowAdapter;
> import java.awt.event.WindowEvent;
> import java.lang.ref.WeakReference;
> import java.lang.reflect.Field;
> import java.util.Enumeration;
> import java.util.Vector;
> 
> /**
>  * The following Frame App has two Windows. Clicking on the buttons toggle
>  * between the two windows. Each time a Window is set visible, it creates 100
>  * child windows. When the other window is hidden, it disposes all its child
>  * windows. Using reflection, the app counts the total number of WeakReferences
>  * in the Window.ownedWindowList Vector, displaying the total counts of child
>  * windows created, the total number of WeakReferences that contain null
>  * references, and the total number of WeakReferences that refer to a child
>  * Window.
>  */
> public class MainFrame extends Frame {
> 
>     Window parentWindow1 = new ParentWindow(this, 1);
>     Window parentWindow2 = new ParentWindow(this, 2);
> 
>     public MainFrame() {
>         super("Mem Leak Test1");
> 
>         addWindowListener(new WindowAdapter() {
>             public void windowClosing(WindowEvent evt) {
>                 dispose();
>             }
>         });
> 
>         parentWindow1.setVisible(true);
>     }
> 
>     public static void main(String[] args) {
>         EventQueue.invokeLater(new Runnable() {
>             public void run() {
>                 new MainFrame().setVisible(true);
>             }
>         });
>     }
> }
> 
> class ParentWindow extends Window {
> 
>     private static final int NUM_WINS   = 100;
>     private static final int NULL_INDEX =   0;
>     private static final int WEAK_INDEX =   1;
> 
>     private static int numChildWindowsCreated;
> 
>     private Window[] childWindows;
> 
>     public ParentWindow(Window owner, int num) {
>         super(owner);
> 
>         Button button = new Button("Click");
> 
>         add(new Label("Window " + num), BorderLayout.NORTH);
>         add(button);
> 
>         button.addActionListener(new ClickAction());
> 
>         pack();
>     }
> 
>     public void setVisible(boolean b) {
>         super.setVisible(b);
> 
>         if (b) {
>             createWindows();
>         } else {
>             disposeWindows();
>         }
>     }
> 
>     private void createWindows() {
>         childWindows = new Window[NUM_WINS];
> 
>         for (int i = 0; i < childWindows.length; i++) {
>             childWindows[i] = new Window(this);
>             numChildWindowsCreated++;
>         }
>     }
> 
>     private void disposeWindows() {
>     	for (int i = 0; i < childWindows.length; i++) {
>             childWindows[i].dispose();
>             childWindows[i] = null;
>     	}
> 
>         childWindows = null;
>     }
> 
>     private class ClickAction implements ActionListener {
> 
>         public void actionPerformed(ActionEvent evt) {
>             MainFrame owner = (MainFrame) getOwner();
> 
>             Window other = (ParentWindow.this == owner.parentWindow1)
>                     ? owner.parentWindow2 : owner.parentWindow1;
> 
>             setVisible(false);
>             other.setVisible(true);
> 
>             int[] counts = new int[2];
> 
>             countOwnedWindows(owner.parentWindow1, counts);
>             countOwnedWindows(owner.parentWindow2, counts);
> 
>             System.out.println("*********************************");
>             System.out.println("Win  Count: " + numChildWindowsCreated);
>             System.out.println("Null Count: " + counts[NULL_INDEX]);
>             System.out.println("Weak Count: " + counts[WEAK_INDEX]);
>         }
> 
>         private void countOwnedWindows(Window window, int[] counts) {
>             try {
>                 Field field = Window.class.getDeclaredField("ownedWindowList");
>                 field.setAccessible(true);
>                 
>                 Vector vector = (Vector) field.get(window);
>                 
>                 Enumeration e = vector.elements();
>                 
>                 while (e.hasMoreElements()) {
>                     WeakReference ref = (WeakReference) e.nextElement();
>                     
>                     if (ref.get() == null) {
>                         counts[NULL_INDEX]++;
>                     } else {
>                         counts[WEAK_INDEX]++;
>                     }
>                 }
>             //IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException
>             } catch (Exception ex) {
>                 ex.printStackTrace();
>                 System.exit(0);
>             }
>         }
>     }
> }
> 

> Sample output:
>
> *********************************
> Win  Count: 200
> Null Count: 0
> Weak Count: 200
> *********************************
> Win  Count: 300
> Null Count: 0
> Weak Count: 300
> *********************************
> Win  Count: 400
> Null Count: 0
> Weak Count: 400
> *********************************
> Win  Count: 500
> Null Count: 0
> Weak Count: 500
> *********************************
> Win  Count: 600
> Null Count: 0
> Weak Count: 600
> *********************************
> Win  Count: 700
> Null Count: 0
> Weak Count: 700
> *********************************
> Win  Count: 800
> Null Count: 579
> Weak Count: 221
> *********************************
> Win  Count: 900
> Null Count: 579
> Weak Count: 321
> *********************************
> Win  Count: 1000
> Null Count: 579
> Weak Count: 421
> *********************************
> Win  Count: 1100
> Null Count: 579
> Weak Count: 521
> *********************************
> Win  Count: 1200
> Null Count: 579
> Weak Count: 621
> *********************************
> Win  Count: 1300
> Null Count: 579
> Weak Count: 721
> *********************************
> Win  Count: 1400
> Null Count: 1176
> Weak Count: 224
> *********************************
> Win  Count: 1500
> Null Count: 1176
> Weak Count: 324
> *********************************
> Win  Count: 1600
> Null Count: 1176
> Weak Count: 424
> *********************************
> Win  Count: 1700
> Null Count: 1176
> Weak Count: 524
> *********************************
> Win  Count: 1800
> Null Count: 1176
> Weak Count: 624
> *********************************
> Win  Count: 1900
> Null Count: 1176
> Weak Count: 724
> *********************************
> Win  Count: 2000
> Null Count: 1756
> Weak Count: 244
> *********************************
> Win  Count: 2100
> Null Count: 1756
> Weak Count: 344
> *********************************
> Win  Count: 2200
> Null Count: 1756
> Weak Count: 444
> *********************************
> Win  Count: 2300
> Null Count: 1756
> Weak Count: 544
> *********************************
> Win  Count: 2400
> Null Count: 1756
> Weak Count: 644
> *********************************
> Win  Count: 2500
> Null Count: 1756
> Weak Count: 744
> *********************************
> Win  Count: 2600
> Null Count: 2292
> Weak Count: 308
> *********************************
> Win  Count: 2700
> Null Count: 2292
> Weak Count: 408
> *********************************
> Win  Count: 2800
> Null Count: 2292
> Weak Count: 508
> *********************************
> Win  Count: 2900
> Null Count: 2292
> Weak Count: 608
> *********************************
> Win  Count: 3000
> Null Count: 2292
> Weak Count: 708
> *********************************
> Win  Count: 3100
> Null Count: 2792
> Weak Count: 308
> *********************************
> Win  Count: 3200
> Null Count: 2792
> Weak Count: 408
> *********************************
> Win  Count: 3300
> Null Count: 2792
> Weak Count: 508
> *********************************
> Win  Count: 3400
> Null Count: 2792
> Weak Count: 608
> *********************************
> Win  Count: 3500
> Null Count: 2792
> Weak Count: 708
> *********************************
> Win  Count: 3600
> Null Count: 2792
> Weak Count: 808
> *********************************
> Win  Count: 3700
> Null Count: 2997
> Weak Count: 703
> *********************************
> Win  Count: 3800
> Null Count: 2997
> Weak Count: 803
> *********************************
> Win  Count: 3900
> Null Count: 2997
> Weak Count: 903
> *********************************
> Win  Count: 4000
> Null Count: 2997
> Weak Count: 1003
> *********************************
> Win  Count: 4100
> Null Count: 2997
> Weak Count: 1103
> *********************************
> Win  Count: 4200
> Null Count: 2997
> Weak Count: 1203
> *********************************
> Win  Count: 4300
> Null Count: 3509
> Weak Count: 791
> *********************************
> Win  Count: 4400
> Null Count: 3509
> Weak Count: 891
> *********************************
> Win  Count: 4500
> Null Count: 3509
> Weak Count: 991
> *********************************
> Win  Count: 4600
> Null Count: 3509
> Weak Count: 1091
> *********************************
> Win  Count: 4700
> Null Count: 3509
> Weak Count: 1191
> *********************************
> Win  Count: 4800
> Null Count: 4009
> Weak Count: 791
> *********************************
> Win  Count: 4900
> Null Count: 4009
> Weak Count: 891
> *********************************
> Win  Count: 5000
> Null Count: 4009
> Weak Count: 991
> *********************************
> Win  Count: 5100
> Null Count: 4009
> Weak Count: 1091
> *********************************
> Win  Count: 5200
> Null Count: 4009
> Weak Count: 1191
> *********************************
> Win  Count: 5300
> Null Count: 4009
> Weak Count: 1291
> *********************************
> Win  Count: 5400
> Null Count: 4371
> Weak Count: 1029
> *********************************
> Win  Count: 5500
> Null Count: 4371
> Weak Count: 1129
> *********************************
> Win  Count: 5600
> Null Count: 4371
> Weak Count: 1229
> *********************************
> Win  Count: 5700
> Null Count: 4371
> Weak Count: 1329
> *********************************
> Win  Count: 5800
> Null Count: 4371
> Weak Count: 1429
> *********************************
> Win  Count: 5900
> Null Count: 4871
> Weak Count: 1029
> *********************************
> Win  Count: 6000
> Null Count: 4871
> Weak Count: 1129
> *********************************
> Win  Count: 6100
> Null Count: 4871
> Weak Count: 1229
> *********************************
> Win  Count: 6200
> Null Count: 4871
> Weak Count: 1329
> *********************************
> Win  Count: 6300
> Null Count: 4871
> Weak Count: 1429
> *********************************
> Win  Count: 6400
> Null Count: 4871
> Weak Count: 1529
> *********************************
> Win  Count: 6500
> Null Count: 5362
> Weak Count: 1138
> *********************************
> Win  Count: 6600
> Null Count: 5362
> Weak Count: 1238
> *********************************
> Win  Count: 6700
> Null Count: 5362
> Weak Count: 1338
> *********************************
> Win  Count: 6800
> Null Count: 5362
> Weak Count: 1438
> *********************************
> Win  Count: 6900
> Null Count: 5362
> Weak Count: 1538
> *********************************
> Win  Count: 7000
> Null Count: 5855
> Weak Count: 1145
> *********************************
> Win  Count: 7100
> Null Count: 5855
> Weak Count: 1245
> *********************************
> Win  Count: 7200
> Null Count: 5855
> Weak Count: 1345
> *********************************
> Win  Count: 7300
> Null Count: 5855
> Weak Count: 1445
> *********************************
> Win  Count: 7400
> Null Count: 5855
> Weak Count: 1545
> *********************************
> Win  Count: 7500
> Null Count: 6355
> Weak Count: 1145
> *********************************
> Win  Count: 7600
> Null Count: 6355
> Weak Count: 1245
> *********************************
> Win  Count: 7700
> Null Count: 6355
> Weak Count: 1345
> *********************************
> Win  Count: 7800
> Null Count: 6355
> Weak Count: 1445
> *********************************
> Win  Count: 7900
> Null Count: 6355
> Weak Count: 1545
> *********************************
> Win  Count: 8000
> Null Count: 6355
> Weak Count: 1645
> *********************************
> Win  Count: 8100
> Null Count: 6816
> Weak Count: 1284
> *********************************
> Win  Count: 8200
> Null Count: 6816
> Weak Count: 1384
> *********************************
> Win  Count: 8300
> Null Count: 6816
> Weak Count: 1484
> *********************************
> Win  Count: 8400
> Null Count: 6816
> Weak Count: 1584
> 

> [Message sent by forum member 'wwwizard' (wwwizard)]
>
> http://forums.java.net/jive/thread.jspa?messageID=304278


wwwizard

Posts: 10
Re: Removed finalize() in java.awt.Window in Java SE 6
Posted: Oct 9, 2008 5:44 AM   in response to: Artem Ananiev
  Click to reply to this thread Reply

> The leak looks strange, because only WeakReferences
> are stored for child
> windows, and these references can be freed by GC at
> any time. Could you
> provide a short test which can be used to reproduce
> the leak?

The child windows are GCed, but the Window.ownedWindowList Vector keeps the references to the WeakReferences which are not GCed.

Artem Ananiev
Re: Removed finalize() in java.awt.Window in Java SE 6
Posted: Oct 9, 2008 5:49 AM   in response to: wwwizard
  Click to reply to this thread Reply


swing@javadesktop.org wrote:
>> The leak looks strange, because only WeakReferences
>> are stored for child
>> windows, and these references can be freed by GC at
>> any time. Could you
>> provide a short test which can be used to reproduce
>> the leak?
>
> The child windows are GCed, but the Window.ownedWindowList Vector keeps the references to the WeakReferences which are not GCed.

This looks odd, because weak reference is removed from parent's list
when the corresponding window is collected...

Thanks,

Artem

> [Message sent by forum member 'wwwizard' (wwwizard)]
>
> http://forums.java.net/jive/thread.jspa?messageID=304281


wwwizard

Posts: 10
Re: Removed finalize() in java.awt.Window in Java SE 6
Posted: Oct 9, 2008 9:46 AM   in response to: Artem Ananiev
  Click to reply to this thread Reply

I ran the above code in the NetBeans debugger. I just started the app and checked the number of instances of WindowDisposerRecord. I had 103 instances:

1 MainFrame
2 ParentWindows
100 child Windows

All of the WindowDisposerRecord.owners return null.

static class WindowDisposerRecord implements sun.java2d.DisposerRecord {
    final WeakReference<Window> owner;
    final WeakReference weakThis;
    final AppContext context;
    WindowDisposerRecord(AppContext context, Window victim) {
        owner = new WeakReference<Window>(victim.getOwner());
        weakThis = victim.weakThis;
        this.context = context;
    }
    public void dispose() {
        Window parent = owner.get();            //always returns null
        if (parent != null) {                   //so it will never enter if
            parent.removeOwnedWindow(weakThis); //WeakRef never removed from OwnedWindowList
        }
        Window.removeFromWindowList(context, weakThis);
    }
}


In dispose(), the parent is always null, so it never enters the if block, so it doesn't remove the WeakReference from the ownedWindowList.

In this example, the Disposer doesn't seem to be able to properly dispose WeakReferences to Windows.

trembovetski

Posts: 644
Re: Removed finalize() in java.awt.Window in Java SE 6
Posted: Oct 10, 2008 10:31 PM   in response to: wwwizard
  Click to reply to this thread Reply

If parent returned from get is null it means that it has already been collected, which means that there's nothing to remove the reference from.

Dmitri

wwwizard

Posts: 10
Re: Removed finalize() in java.awt.Window in Java SE 6
Posted: Oct 12, 2008 6:01 PM   in response to: trembovetski
  Click to reply to this thread Reply

In the sample code above, the MainFrame has strong references to the two parent Windows, so these two windows are never GCed. Yet when the child windows are disposed with the WindowDisposerRecord, the WeakReferences to the parents are null, even tho the parents are still strongly referenced.So the child windows are never removed from the two parent windows.

We automated our app to run for three days. There was over 200000 WeakReferences. The huge majority of these WeakReferences are held by the ownedWindowList Vector in Window.

Artem Ananiev
Re: Removed finalize() in java.awt.Window in Java SE 6
Posted: Oct 13, 2008 2:43 AM   in response to: wwwizard
  Click to reply to this thread Reply


swing@javadesktop.org wrote:
> I ran the above code in the NetBeans debugger. I just started the app and checked the number of instances of WindowDisposerRecord. I had 103 instances:
>
> 1 MainFrame
> 2 ParentWindows
> 100 child Windows
>
> All of the WindowDisposerRecord.owners return null.

OK, I see... I have just filed a bug 6758673 against AWT, it will be
visible via bugs.sun.com in a few hours or so.

The root cause of the problem is that WindowDisposerRecord is created
too early - in init(gc) - when victim's owner hasn't been initialized
yet. To fix the bug we just need to move WDR creation from init() to
ownedInit().

Thanks,

Artem

>
> static class WindowDisposerRecord implements sun.java2d.DisposerRecord {
>     final WeakReference<Window> owner;
>     final WeakReference weakThis;
>     final AppContext context;
>     WindowDisposerRecord(AppContext context, Window victim) {
>         owner = new WeakReference<Window>(victim.getOwner());
>         weakThis = victim.weakThis;
>         this.context = context;
>     }
>     public void dispose() {
>         Window parent = owner.get();            //always returns null
>         if (parent != null) {                   //so it will never enter if
>             parent.removeOwnedWindow(weakThis); //WeakRef never removed from OwnedWindowList
>         }
>         Window.removeFromWindowList(context, weakThis);
>     }
> }
> 

>
> In dispose(), the parent is always null, so it never enters the if block, so it doesn't remove the WeakReference from the ownedWindowList.
>
> In this example, the Disposer doesn't seem to be able to properly dispose WeakReferences to Windows.
> [Message sent by forum member 'wwwizard' (wwwizard)]
>
> http://forums.java.net/jive/thread.jspa?messageID=304356





 XML java.net RSS