6688203: Memory leak and performance problems in the method getFileSystemView of FileSystemView
authorrupashka
Thu, 01 May 2008 14:47:50 +0400
changeset 462 5c2ae7cc263d
parent 461 67f5e7e1b94a
child 463 435cd1cc42b6
6688203: Memory leak and performance problems in the method getFileSystemView of FileSystemView Summary: Removed from the "FileSystemView#getFileSystemView" method creation of a new listener and adding it to UIManager Reviewed-by: peterz
jdk/src/share/classes/javax/swing/filechooser/FileSystemView.java
jdk/test/javax/swing/JFileChooser/6688203/bug6688203.java
--- a/jdk/src/share/classes/javax/swing/filechooser/FileSystemView.java	Wed Apr 30 08:23:31 2008 -0700
+++ b/jdk/src/share/classes/javax/swing/filechooser/FileSystemView.java	Thu May 01 14:47:50 2008 +0400
@@ -26,26 +26,18 @@
 package javax.swing.filechooser;
 
 
-import javax.swing.event.*;
 import javax.swing.*;
 
 import java.awt.Image;
 import java.io.File;
-import java.io.FileFilter;
-import java.io.FilenameFilter;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
 import java.util.Vector;
+import java.lang.ref.WeakReference;
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeEvent;
 
-
-import java.lang.reflect.*;
-
 import sun.awt.shell.*;
 
 /**
@@ -74,18 +66,11 @@
     static FileSystemView unixFileSystemView = null;
     //static FileSystemView macFileSystemView = null;
     static FileSystemView genericFileSystemView = null;
-    static boolean useSystemExtensionsHiding = false;
+
+    private boolean useSystemExtensionHiding =
+            UIManager.getDefaults().getBoolean("FileChooser.useSystemExtensionHiding");
 
     public static FileSystemView getFileSystemView() {
-        useSystemExtensionsHiding = UIManager.getDefaults().getBoolean("FileChooser.useSystemExtensionHiding");
-        UIManager.addPropertyChangeListener(new PropertyChangeListener() {
-            public void propertyChange(PropertyChangeEvent e) {
-               if (e.getPropertyName().equals("lookAndFeel")) {
-                   useSystemExtensionsHiding = UIManager.getDefaults().getBoolean("FileChooser.useSystemExtensionHiding");
-               }
-            }
-        });
-
         if(File.separatorChar == '\\') {
             if(windowsFileSystemView == null) {
                 windowsFileSystemView = new WindowsFileSystemView();
@@ -113,6 +98,26 @@
         return genericFileSystemView;
     }
 
+    public FileSystemView() {
+        final WeakReference<FileSystemView> weakReference = new WeakReference<FileSystemView>(this);
+
+        UIManager.addPropertyChangeListener(new PropertyChangeListener() {
+            public void propertyChange(PropertyChangeEvent evt) {
+                FileSystemView fileSystemView = weakReference.get();
+
+                if (fileSystemView == null) {
+                    // FileSystemView was destroyed
+                    UIManager.removePropertyChangeListener(this);
+                } else {
+                    if (evt.getPropertyName().equals("lookAndFeel")) {
+                        fileSystemView.useSystemExtensionHiding =
+                                UIManager.getDefaults().getBoolean("FileChooser.useSystemExtensionHiding");
+                    }
+                }
+            }
+        });
+    }
+
     /**
      * Determines if the given file is a root in the navigatable tree(s).
      * Examples: Windows 98 has one root, the Desktop folder. DOS has one root
@@ -170,7 +175,7 @@
         if (f != null) {
             name = f.getName();
             if (!name.equals("..") && !name.equals(".") &&
-                (useSystemExtensionsHiding ||
+                (useSystemExtensionHiding ||
                  !isFileSystem(f) ||
                  isFileSystemRoot(f)) &&
                 ((f instanceof ShellFolder) ||
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JFileChooser/6688203/bug6688203.java	Thu May 01 14:47:50 2008 +0400
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+   @bug 6688203
+   @summary Memory leak and performance problems in the method getFileSystemView of FileSystemView
+   @author Pavel Porvatov
+   @run main bug6688203
+*/
+
+import javax.swing.*;
+import javax.swing.filechooser.FileSystemView;
+import java.io.File;
+import java.lang.reflect.Field;
+
+public class bug6688203 {
+    public static void main(String[] args) {
+        // Create an instance of FileSystemView
+        FileSystemView.getFileSystemView();
+
+        int startCount = UIManager.getPropertyChangeListeners().length;
+
+        for (int i = 0; i < 100; i++) {
+            FileSystemView.getFileSystemView();
+        }
+
+        if (startCount != UIManager.getPropertyChangeListeners().length) {
+            throw new RuntimeException("New listeners were added into UIManager");
+        }
+
+        FileSystemView fileSystemView = FileSystemView.getFileSystemView();
+        File file = new File("Some file");
+
+        for (UIManager.LookAndFeelInfo lafInfo : UIManager.getInstalledLookAndFeels()) {
+            try {
+                UIManager.setLookAndFeel(lafInfo.getClassName());
+            } catch (Exception e) {
+                // Ignore such errors
+                System.out.println("Cannot set LAF " + lafInfo.getName());
+
+                continue;
+            }
+
+            fileSystemView.getSystemDisplayName(file);
+
+            try {
+                Field field = FileSystemView.class.getDeclaredField("useSystemExtensionHiding");
+
+                field.setAccessible(true);
+
+                Boolean value = field.getBoolean(fileSystemView);
+
+                if (value != UIManager.getDefaults().getBoolean("FileChooser.useSystemExtensionHiding")) {
+                    throw new RuntimeException("Invalid cached value of the FileSystemView.useSystemExtensionHiding field");
+                }
+            } catch (Exception e) {
+                throw new RuntimeException("Cannot read the FileSystemView.useSystemExtensionHiding field", e);
+            }
+        }
+    }
+}