United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4836635 Resource leak in JFileChooser Windows L&F
JDK-4836635 : Resource leak in JFileChooser Windows L&F

Details
Type:
Bug
Submit Date:
2003-03-24
Status:
Resolved
Updated Date:
2003-05-25
Project Name:
JDK
Resolved Date:
2003-05-25
Component:
client-libs
OS:
windows_2003,windows_2000
Sub-Component:
javax.swing
CPU:
x86
Priority:
P2
Resolution:
Fixed
Affected Versions:
1.4.2,1.4.2_09
Fixed Versions:
5.0 (tiger)

Related Reports
Backport:

Sub Tasks

Description
Name: ssR10077			Date: 03/24/2003

###@###.###
The following test case leaks about 1600 GDI objects. Bug is reproducible
only with Windows L&F. With Metal L&F it eats <100 GDI objects.

import java.io.*;
import java.awt.*;
import javax.swing.*;

public class Test {
    public static void main(String[] args) throws Throwable {

UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel
");
        new Test();
    }

    public Test() {
        JFrame frame = new JFrame();
        frame.setSize(500,500);
        frame.show();

        for (int i = 0; i < 20; i++) {
            JFileChooser chooser = new JFileChooser();
            frame.getContentPane().add(chooser);
            frame.validate();
            frame.repaint();
            try { Thread.sleep(10); } catch (Throwable e) {};
            frame.getContentPane().remove(chooser);
            frame.validate();
            frame.repaint();
            try { Thread.sleep(10); } catch (Throwable e) {};
            System.gc();
            System.gc();
        }
    }
}

======================================================================

                                    

Comments
SUGGESTED FIX



Name: ssR10077			Date: 03/25/2003



------- Win32ShellFolder2.java -------
*** /tmp/dOxaqmb	Tue Mar 25 16:49:48 2003
--- Win32ShellFolder2.java	Tue Mar 25 16:58:41 2003
***************
*** 352,362 ****
  	return path1.equalsIgnoreCase(path2);
      }
  
      /**
       * Check to see if two ShellFolder objects are the same
       */
      public boolean equals(Object o) {
!         if (o == null || !(o instanceof Win32ShellFolder2)) {
  	    // Short-circuit circuitous delegation path
  	    if (!(o instanceof File)) {
  		return super.equals(o);
--- 352,377 ----
  	return path1.equalsIgnoreCase(path2);
      }
  
+ 
+     public int hashCode() {
+         String path = getPath();
+         if (path == null) {
+             return 0;
+         }
+         return path.toUpperCase().hashCode();
+     }
+     
      /**
       * Check to see if two ShellFolder objects are the same
       */
      public boolean equals(Object o) {
!         if (o == null) {
!             return super.equals(o);
!         }
!         if (hashCode() != o.hashCode()) {
!             return false;
!         }
!         if (!(o instanceof Win32ShellFolder2)) {
  	    // Short-circuit circuitous delegation path
  	    if (!(o instanceof File)) {
  		return super.equals(o);
***************
*** 483,488 ****
--- 498,504 ----
  	    int testedAttrs = ATTRIB_FILESYSTEM | ATTRIB_FILESYSANCESTOR;
  	    do {
  		childPIDL = getNextChild(pEnumObjects);
+                 boolean releasePIDL=true;
  		if (childPIDL != 0 &&
  		    (getAttributes0(pIShellFolder, childPIDL, testedAttrs) & 
testedAttrs) != 0) {
  		    Win32ShellFolder2 childFolder = null;
***************
*** 490,501 ****
  			&& personal != null
  			&& pidlsEqual(pIShellFolder, childPIDL, personal.relativePIDL)) 
{
  			childFolder = personal;
- 			releasePIDL(childPIDL);
  		    } else {
  			childFolder = new Win32ShellFolder2(this, childPIDL);
  		    }
  		    list.add(childFolder);
  		}
  	    } while (childPIDL != 0);
  	    releaseEnumObjects(pEnumObjects);
  	}
--- 506,520 ----
  			&& personal != null
  			&& pidlsEqual(pIShellFolder, childPIDL, personal.relativePIDL)) 
{
  			childFolder = personal;
  		    } else {
  			childFolder = new Win32ShellFolder2(this, childPIDL);
+                         releasePIDL=false;
  		    }
  		    list.add(childFolder);
  		}
+                 if (releasePIDL) {
+                     releasePIDL(childPIDL);
+ 		}
  	    } while (childPIDL != 0);
  	    releaseEnumObjects(pEnumObjects);
  	}
***************
*** 523,528 ****
--- 542,548 ----
  		    break;
  		}
  	    }
+             releasePIDL(childPIDL);            
  	}
  	releaseEnumObjects(pEnumObjects);
  	return child;
***************
*** 674,691 ****
  
  
      private Image makeIcon(long hIcon, boolean getLargeIcon) {
! 	if (hIcon > 0L) {
  	    // Get the bits.  This has the side effect of setting the imageHash value 
for this object.
  	    int size = getLargeIcon ? 32 : 16;
  	    int[] iconBits = getIconBits(hIcon, size);
  	    if (iconBits != null) {
! 		BufferedImage img = new BufferedImage(size, size, 
BufferedImage.TYPE_INT_ARGB);
  		img.setRGB(0, 0, size, size, iconBits, 0, size);
- 		return img;
  	    }
  	    disposeIcon(hIcon);
  	}
! 	return null;
      }
  
  
--- 694,711 ----
  
  
      private Image makeIcon(long hIcon, boolean getLargeIcon) {
! 	BufferedImage img = null;
!         if (hIcon > 0L) {
  	    // Get the bits.  This has the side effect of setting the imageHash value 
for this object.
  	    int size = getLargeIcon ? 32 : 16;
  	    int[] iconBits = getIconBits(hIcon, size);
  	    if (iconBits != null) {
! 		img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
  		img.setRGB(0, 0, size, size, iconBits, 0, size);
  	    }
  	    disposeIcon(hIcon);
  	}
! 	return img;
      }

------- Win32ShellFolderManager2.java -------
*** /tmp/dFUaWhb	Tue Mar 25 14:58:33 2003
--- Win32ShellFolderManager2.java	Tue Mar 25 14:57:16 2003
***************
*** 49,60 ****
  
      static Win32ShellFolder2 createShellFolderFromRelativePIDL(Win32ShellFolder2 
parent, long pIDL) {
  	// Walk down this relative pIDL, creating new nodes for each of the entries
  	while (pIDL != 0) {
  	    long curPIDL = Win32ShellFolder2.copyFirstPIDLEntry(pIDL);
  	    if (curPIDL != 0) {
  		parent = new Win32ShellFolder2(parent, curPIDL);
- 		pIDL = Win32ShellFolder2.getNextPIDLEntry(pIDL);
  	    }
  	}
  	return parent;
      }
--- 49,65 ----
  
      static Win32ShellFolder2 createShellFolderFromRelativePIDL(Win32ShellFolder2 
parent, long pIDL) {
  	// Walk down this relative pIDL, creating new nodes for each of the entries
+         long oldPIDL = 0;
  	while (pIDL != 0) {
  	    long curPIDL = Win32ShellFolder2.copyFirstPIDLEntry(pIDL);
  	    if (curPIDL != 0) {
  		parent = new Win32ShellFolder2(parent, curPIDL);
  	    }
+             pIDL = Win32ShellFolder2.getNextPIDLEntry(pIDL);
+             if (oldPIDL != 0) {
+                 Win32ShellFolder2.releasePIDL(oldPIDL);
+             }
+             oldPIDL = pIDL;    
  	}
  	return parent;
      }


======================================================================

Name: ssR10077			Date: 03/25/2003


------- ShellFolder2.cpp -------
*** /tmp/drBayqb        Tue Mar 25 17:22:51 2003
--- ShellFolder2.cpp    Tue Mar 25 17:22:20 2003
***************
*** 793,799 ****
            hres = pIcon->Extract(szBuf, index, &hIconLarge, &hIcon, (16 << 16) + 32);
            if (SUCCEEDED(hres)) {
                if (getLargeIcon) {
!                   hIcon = hIconLarge;
                }
            }
        }
--- 793,802 ----
            hres = pIcon->Extract(szBuf, index, &hIconLarge, &hIcon, (16 << 16) + 32);
            if (SUCCEEDED(hres)) {
                if (getLargeIcon) {
!                     fn_DestroyIcon((HICON)hIcon);
!                     hIcon = hIconLarge;
!                 } else {
!                     fn_DestroyIcon((HICON)hIconLarge);
                }
            }
        }

======================================================================
                                     
2004-06-11
EVALUATION

I can reproduce this on Windows 2000.  I'm seeing approximately the same number of leaked resources with 1.4.1 and 1.4.2 (800+).  This is not a regression from 1.4.1, so committing to Tiger.
###@###.### 2003-03-24


Name: ssR10077			Date: 03/25/2003


The leak is in BasicFileChooserUI's  BasicFileView, which has a HashMap of
icons that are keyed by File instances and which can be Win32ShellFolder2
objects as well. It is caused by improper caching of icons due to
inconsistency of equals() and hashCode() of Win32ShellFolder2. The problem
is that the equal items should have the same hashCode() otherwise HashMap
messes up. Which isn't true for Win32ShellFolder2 equals(). Also
Win32ShellFolder2 has another resource leak with PIDL.




======================================================================
                                     
2004-06-11
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
tiger

FIXED IN:
tiger

INTEGRATED IN:
tiger
tiger-b08


                                     
2004-06-14



Hardware and Software, Engineered to Work Together