Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4712307
Votes 1
Synopsis JFileChooser is very slow when browsing many files in a directory
Category java:classes_swing
Reported Against hopper-beta
Release Fixed 1.4.2(mantis-b17)
State 10-Fix Delivered, bug
Priority: 2-High
Related Bugs 4480327 , 4679673 , 4711700 , 4858226 , 4889108 , 5033747
Submit Date 09-JUL-2002
Description




FULL PRODUCT VERSION :
java version "1.4.1-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-beta-b14)
Java HotSpot(TM) Client VM (build 1.4.1-beta-b14, mixed mode)


FULL OPERATING SYSTEM VERSION :
Windows 98 [Version 4.10.2222]

A DESCRIPTION OF THE PROBLEM :
Using the file chooser, browse to a directory with many files,

the dialog takes a long time to show.  After it shows, it
will takes a long time to show the files.

The folder I tested with has:
1545 files and 49 folders.  Note that Notepad.exe open this
instantly.

There is a related bug that is closed:   4621272
It says that it fixes the bug in hopper, unfortunately, I
have no way of knowing if j2sdk1.4.1 beta is "hopper" or not.

Also, note that the 2 bugs are different.  The related bug
show slowness when select many files.

This bug shows slowness by merely open a directory.

Also note that with j2sdk1.4.1 beta, the previous bug is
still there, and select 1 file, the select another file,
there is a long pause between (inconsistently though, and
only happen in a directory with many files - note: just
select 1 file, not many files).



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) Run the application
1) Open a JFileChooser
2) Browse to a directory that has many files
 (it's even better to have the first directory of
JFileChooser to have many files to show the effect of slowness).

EXPECTED VERSUS ACTUAL BEHAVIOR :
Things work faster.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import javax.swing.*;
import java.io.*;

public class BugDemonstration
{
	public static void main(String args[])
	{
		final JFrame frame = new JFrame("The Frame");
        frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
		frame.setSize(200,200);
        frame.setVisible(true);

        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                JFileChooser file = new JFileChooser();
                file.setMultiSelectionEnabled(true);
                file.setDialogTitle
                    ("Select lots of files..." );
                file.showDialog(frame.getContentPane(), "Demonstrate problem");
                File [] selected = file.getSelectedFiles();
                System.out.println (selected.length+" files selected.");
            }
        });
    }
}
---------- END SOURCE ----------
(Review ID: 158588) 
======================================================================
Work Around
N/A
Evaluation
The problem has been solved through a number of improvements in
filechooser and shellfolder code. Primarily, the trick was to
no longer separate the codepaths in Win32ShellFolder between
fileystem objects and special shellfolders, but instead take
advantage of the Win32 Shell API to get all the information
we need. By totally avoiding any loops hitting the java.io.File
class for information (such as exists() and isDirectory()) we
managed to speed things up by several 100 x.

There were also some improvements made in the efficiency of
filechooser loops. These changes will also benefit other platforms
than win32. See also the evaluation of bug 4679673.

Note: In case the new changes should cause new problems (regressions)
in 1.4.2, the bugfix can be turned off by adding the following switch
to the command line: -Dswing.disableFileChooserSpeedFix.

 xxxxx@xxxxx  2003-02-13
Comments
  
  Include a link with my name & email   

Submitted On 05-AUG-2002
wisa
This bug might be related to the slow performance of the
isDirectory method that is used in the file filter that
separates the directories from the rest of the files. The
bug has previously been reported as 4145781 and possibly 
4071318. 

I can also always reproduce the bug on Windows 98 but it
does not seem to exist on NT, and the previous bugs were
closed because it could not be produced by Sun on Win95.
There is a <a
href="http://www.javalobby.org/thread.jsp?forum=61&thread=4587">thread</a>
about this bug at Javalobby that suggests that the slowness
lies in the Windows routine that Java's isDirectory method uses.


Submitted On 26-AUG-2002
werpu
I tried a program of mine with 1.4.1 RC under XP and this
bug is reproducable, hopfully it will be fixed in the final.


Submitted On 27-AUG-2002
werpu
additioncal comment: I rather doubt it is the windows routine, 
since it worked flawlessly in the 1.3 series unless isdirectory is 
resolved differently in 1.4.1 than in the 1.3 series. 


Submitted On 28-AUG-2002
werpu
Sorry WISA, but you posted the wrong thread:

http://www.javalobby.org/threadMode3.jsp?
message=521913&thread=4587&forum=61

According to this thread the isDirectory does indeed do an 
API call, it just uses a buggy one (not used by the Windows 
Explorer), some guy in the posted JavaLobby thread worked 
around the problem by implementing a JNI call which called a 
different function and that speeded things up significantly. 
Maybe Sun should contact this guy. The isDirectory problem 
has been posted since 1.1.6 according to the bug database 
and always was rejected although being constantly there!

Anyway you guys should really have a look at the thread it is 
quite informative regarding the problem. 


Submitted On 18-SEP-2002
franrein
I am having the same problems with JFileChooser. For the 
Windows platform the performance is very close to 
unacceptable limits when a directory with a lot of files is 
requested. If we add to this mix the network, well... the 
thing becomes very very slow. This, for a UNIX user might 
be ok but for a Windows user is not acceptable.
Windows native file dialog does not have that problem, and 
Java's version does. So my point is, why don't they forget 
about the JFileChooser and write another one using the 
native from Windows? Sun already did that with the Print 
Dialog, so why don't do the same with this functionality that 
is used by 99% of applications 100% of the time.


Submitted On 21-OCT-2002
macgibbon
The isDirectory() method uses the _stati64 call. Under 
Window98 FAT, this appears to be a linear search through the 
directory. As the directory get larger, the linear search get 
longer and has to be done more times so the total time blows 
up in N squared order. Under NTFS, the file lookup seems to 
be better behaved. 

To be viable on FAT filesystems, we need a method that will 
iterate once through the directory, lookup the directory 
status, file length and last modified and return an array of 
FastFile with file information already assigned. Forcing a linear 
search through the direcroy for every file modified date under 
FAT filesystems isn't viable. 




Submitted On 03-JAN-2003
anicolao
I've seen even worse behaviour under windows 2000 and
windows XP. Using the JFileChooser demo to open a directory
with about 5000 files in it several times in a row, and
moving the filechooser while waiting causes windows to draw
window decorations incorrectly and draw various random
window contents at 0,0 on the display including non-java
applications and empty gray boxes. I speculate that the bad
windows behaviour is related to too many COM shell folder
objects being created by the java code, which appears to
create one of these COM objects for each file in the directory.


Submitted On 21-JAN-2003
jtr
If the native lookups can't be made faster, perhaps
JFileChooser could be taught to be more user friendly. I
personally notice this problem over network filesystem
lookups (which are understandably slow).

Windows uses a "flashlight searching" animation during long
running filesystem lookups. JFileChooser just seems to
freeze. Even worse, when it unfreezes it executes actions
from old keystrokes (where I was clicking because I wasn't
sure if I actually managed to double click the first time).

The animation (perhaps with an abort option?) would be
preferable.


Submitted On 24-JAN-2003
macgibbon
I have been trying to work around this and have a half baked 
prototye using a single native method to cache all file 
attributes when it does the list. It is NOT suitable for 
production as it doesn't have the windows Desktop and it 
reverts to the slow implementation when the directory tree is 
navigated.  The code is at 
http://home.twcny.rr.com/macgibbon/.

Surprisingly the JFileChooser GUI is capable of much faster 
performance. On a new XP 2.8 MHz  P4, the time for 
JFileChooser to open a folder of 40000 files with my native 
method workaround is just 1.7 secs. In contrast, the standard 
JfileChooser takes 34 MINUTES on the same 40000 file folder. 
The workaround is substantially faster on smaller folders as 
well
 
Custom JFileChooser on 893 files took 1050 msec.
Standard JFileChooser on 893 files took 3620 msec.

Custom JFileChooser on 224 files took 1040 msec.
Standard JFileChooser on 224 files took 1760 msec.


Submitted On 03-FEB-2003
rer
From my experimentation I discovered that sometimes the getFiles() method of FileSystemView is called every time the file selection changes so if a user is scrolling the selection this can really slow things down. I also saw some processor time being given to the getSystemDisplayName() call due native calls to a ShellSystem object.

I wrote an implementation that brings the speed up and wanted to pass on a copy. My implementation speeds things up at the cost of the user not being able to create a new folder and some confusion in the root paths. If you can live with these 2 restrictions than I hope this helps you !

You can download the source at 

  http://www.apparc.com/MyFileSystemView.java

or copy it right from here:

import javax.swing.filechooser.*;
import java.io.*;
import java.util.*;

/* This class addresses 2 issues that I can see that contribute 
 * to JFileChooser slowing down:
 *   
 *   1) Calling getFiles() every time the selected file changes. This
 *      happens sporadically and I'm not sure of the cause, but 
 *      obviously this really slows scrolling down !
 *
 *   2) Using the native "ShellFolder" object in getSystemDisplayName().
 *
 * - Rodney Ryan
 */
public class MyFileSystemView extends FileSystemView
{
    private File   cachedDirectory;
    private File[] cachedFileList;

    // Sometimes the Win 1.4.1 JFileChooser will repeatedly
    // call this method when file selection changes even
    // though the user remains in the same directory. This
    // dramatically slows things down ! So, we cache and
    // things speed up.
    public File[] getFiles(File    directory,
                           boolean useFileHiding)
    {
        if ((directory.equals(cachedDirectory)) && (cachedFileList != null)) {
            return cachedFileList;
        } else {
            cachedFileList = null;
            cachedDirectory = directory;
            cachedFileList = directory.listFiles();
            return cachedFileList;
        }
    }

    // The Win 1.4.1 implementatation refers to a
    // native ShellFolder object. Our implementation
    // avoids the native calls at the cost of
    // some freakiness in the "Look In" bar. If you
    // can live with it this will speed things up also.
    public String getSystemDisplayName(File file)
    {
        String name = null;
        
        if (file != null) {
            name = file.getName();
            if (name.length() == 0) {
                name = file.getPath();
            }
        }
        
        return name;
    }

    // This is the same as the GenericFileSystemView
    // class in the source.
    public boolean isRoot(File file)
    {
        if (!file.isAbsolute()) {
            return false;
        }

        String parentPath = file.getParent();
        
        if (parentPath == null) {
            return true;
        } else {
            File parent = new File(parentPath);
            return parent.equals(file);
        }
    }
    
    // My chooser doesn't allow creation of a new directory
    // so this works for me. If you need to do this consult
    // the source to javax.swing.filechooser.FileSystemView
    // for suggestions.
    public File createNewFolder(File inDirectory) throws IOException
    {
        throw new IOException("Folder creation not allowed.");
    }
    
    // My chooser shows all files. Again, if you want to
    // implement this see the source to FileSystemView.
    public boolean isHiddenFile(File f)
    {
        return false;
    }

    // Simple implementation.
    public File[] getRoots()
    {
        return File.listRoots();
    }
}


Submitted On 26-FEB-2003
rer
Here is an updated version of the above file. This one is much
better because I take advantage of the existing FileSystemView.

You can download the source at 

    http://www.apparc.com/MyFileSystemView.java

or copy it right from here:

import javax.swing.filechooser.FileSystemView;
import java.io.*;
import java.util.Vector;

/* In 1.4 the JFileChooser sometimes calls getFiles() every time
 * the selected file changes even though the user remains in the
 * same directory. This happens sporadically but really slows
 * things down. This class addresses that issue by caching the
 * getFiles() call.
 *
 * - Rodney Ryan
 *   rer@apparc.com
 *   Feb 26 2003
 */
public class MyFileSystemView extends FileSystemView
{
    private File   cachedDirectory = null;
    private File[] cachedFileList  = null;

    // Sometimes the 1.4 JFileChooser will repeatedly call this
    // method when the selected file changes even though the
    // user remains in the same directory. We work around this
    // by caching.
    public File[] getFiles(File    directory,
                           boolean useFileHiding)
    {
        if ((cachedDirectory != null) && (cachedFileList != null)) {
            if (directory.equals(cachedDirectory)) {
                return cachedFileList;
            }
        }
        cachedDirectory = directory;
        cachedFileList = directory.listFiles();
        return cachedFileList;
    }

    public boolean isRoot(File file)
    {
        return getFileSystemView().isRoot(file);
    }

    public File createNewFolder(File inDirectory) throws IOException
    {
        return getFileSystemView().createNewFolder(inDirectory);
    }

    public boolean isHiddenFile(File file)
    {
        return getFileSystemView().isHiddenFile(file);
    }

    public File[] getRoots()
    {
        return getFileSystemView().getRoots();                
    }
}


Submitted On 11-JAN-2004
jcobban
I am still observing excessively slow performance in 
1.4.2-02.  At what level is this fixed?


Submitted On 25-FEB-2004
uwtomas
JNI bindings get destroyed in windows 2000. 

The 
sun_awt_shell_Win32ShellFolder_getLinkLocation 
JNI function
does't correct handle COM initialization at 
ShellFolder.cpp(Line 516)
and will allways shutdown COM at line 537. This will 
disconnect all
COM objects and event listeners from the caller thread.

( see JacoZoom forum for details at 
http://groups.yahoo.com/group/jacoZoom/message/15
90 )


Submitted On 22-JUN-2004
natusik123
It is not fixed it is still incredibly slow and sometimes it just dies on you. Try to open any directory that has more than 5000 files. I tried code bellow for FileSystemView it didn't help at all. We need this fix desperately.  So my point is, why don't you 
write another Component  using the 
native from Windows? JFileChooser is incredibly bad 
for systems that biologists working with. Sometimes they have 50 000 files in one directory. And it can be a million in couple more years.


Submitted On 03-MAR-2005
hlavac
_stati64 is somehow broken, see bug 4788458. They should use Win32 API directly instead - GetFileAttributesEx. That does not exhibit the problems of _stati64.


Submitted On 26-MAR-2006
Using exactly this BugDemostration I find JFileChooser has difficulties opening a directory with many sub-directories each with many files.  It is painfully slow.
I am using Windows XP and jdk1.5.0_06



PLEASE NOTE: JDK6 is formerly known as Project Mustang