I have a customer that is still seeing a JNI Global Reference to his
unreferenced objects when using JDK1.2.2_003 that has the fix for bug
4224888. I have tested the sample code below with JDK1.2.2_003
the memory leak still present.
TestCase:
import java.awt.*;
import java.awt.dnd.*;
import java.awt.dnd.peer.*;
import java.awt.event.*;
import java.awt.peer.*;
import javax.swing.*;
public class bugDropTargetLeak extends JFrame
{
DropTarget _dt;
public bugDropTargetLeak()
{
super("Test Window");
_dt = new DropTarget(this, null);
setSize(400, 400);
}
protected void processWindowEvent(WindowEvent we)
{
if (we.getID() == WindowEvent.WINDOW_CLOSING)
{
System.out.println("window closing...");
if (_dt != null)
{
_dt.setComponent(null);
// The following is to workaround the bug in removeDropTarget(), i.e.
// we need to call it twice for it to invoke the native
// removeNativeDropTarget(). getPeer() is a deprecated method, but
// it's the only workaround I know of.
((DropTargetPeer)getPeer()).removeDropTarget(_dt);
// Clear out the variable just so we have less clutter when analyzing
// using HAT.
_dt = null;
}
dispose();
}
super.processWindowEvent(we);
}
public static void main(String[] args)
{
JFrame f = new JFrame("Main Window");
Container cp = f.getContentPane();
JButton b = new JButton("Click me to launch a leaked window");
f.getContentPane().add(b, "North");
b.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
(new bugDropTargetLeak()).setVisible(true);
}
});
b = new JButton("gc()");
f.getContentPane().add(b, "South");
b.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
System.out.print("Calling system.gc() and System.runFinalization(): ");
System.gc();
System.out.print(".");
System.gc();
System.out.print(".");
System.runFinalization();
System.out.print(".");
System.gc();
System.out.print(".");
System.gc();
System.out.print(".");
System.runFinalization();
System.out.print(".");
System.gc();
System.out.print(".");
System.gc();
System.out.println(" done");
}
});
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent we)
{
System.exit(0);
}
});
f.pack();
f.setVisible(true);
}
}