JDK-4440338 : Redundant file loading threads using JFileChooser; deadlock
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.3.1
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2001-04-11
  • Updated: 2018-09-05
Related Reports
Relates :  
Description
Name: boT120536			Date: 04/11/2001


java version "1.3.1-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1-beta-b15)
Java HotSpot(TM) Server VM (build 2.0fcs-E, mixed mode)

/** Demonstrate a bug in {@link javax.swing.JFileChooser}.
 ** <p>
 ** Run the class below in a directory other than the user's home.
 ** The {@link File_Filter#accept} method prints its activity
 ** to {@link System#out} to document the strange behavior.
 ** <p>
 ** A JFileChooser is created with no argument, which should
 ** set the chooser's current directory to the user's home.
 ** The selected file is set to some file in some other
 ** directory.
 ** <p>
 ** 2 [Basic L&F File Loading Thread]s are
 ** created, so that {@link File_Filter#accept} is called
 ** twice on on each file in the selected file's directory.
 ** Even stranger, after the dialog is dismissed, the program
 ** waits for a minute, then starts 2 or more
 ** [Basic L&F File Loading Thread]s
 ** calling {@link File_Filter#accept} on every file in the user's
 ** home directory. Since the user's 'home' is often C:\WINDOWS,
 ** or on a remote server, this can be a fairly lengthy computation.
 ** In a more realistic setting, where the filechooser is just
 ** part of a larger interface, the responsiveness of interaction
 ** suffers.
 ** <p>
 ** It appears that under some JVMs (eg Comapq's Fast JVM for
 ** the alpha architecture and OSF1) the multiple file loading
 ** threads causes a deadlock. However, I haven't been able to
 ** come up with a simple example that shows this.
 **
 ** @author John Alan McDonald
 ** @since 2001-04-09
 **/

public abstract class

JFileChooser_Bug

  extends Object {

  public static final String
  VERSION = "2001-04-09";

  //==========================================================
  // bug demonstration
  //==========================================================

  public static final void
  main (final String[] args)

    throws java.io.IOException {

    final File_Filter filter = new File_Filter();

    javax.swing.JFileChooser chooser;

    chooser = new javax.swing.JFileChooser();
    chooser.setSelectedFile(new java.io.File("./JFileChooser_Bug.java"));
    chooser.setFileFilter(filter);

    final int result = chooser.showOpenDialog(null);

    System.out.println("result=" + result);
    System.out.println("selected file=" + chooser.getSelectedFile());

    System.out.println(System.getProperties()); }

  //==========================================================
  // local classes
  //==========================================================

  private static final class

  File_Filter

    extends javax.swing.filechooser.FileFilter

    implements java.io.FilenameFilter {

    //==========================================================

    public final boolean
    accept (final java.io.File f) {
      System.out.println();
      System.out.println();
      System.out.println();
      
System.out.println("----------------------------------------------------");
      System.out.println("File_Filter.accept(" + f + ")");
      print_threads(System.out);

      return true; }

    //----------------------------------------------------------

    public final boolean
    accept (final java.io.File dir, final String name) {
      return accept(new java.io.File(dir,name)); }

    //----------------------------------------------------------

    public final String
    getDescription () { return "any file"; }

    //==========================================================

    public
    File_Filter () { super(); }

    //==========================================================
    } // end local class
    //==========================================================

  //==========================================================
  // class methods
  //==========================================================
  //----------------------------------------------------------
  // listing all threads
  //----------------------------------------------------------
  /** @return the root ancestor of the given
   ** {@link ThreadGroup group}.
   **/

  public static final ThreadGroup
  root_ThreadGroup (final ThreadGroup group) {

    final ThreadGroup
    parent = group.getParent();
    if (null == parent) { return group; }
    else { return root_ThreadGroup(parent); }  }

   /** @return the root {@link ThreadGroup} for the current
   ** {@link Thread}.
   **/

  public static final ThreadGroup
  root_ThreadGroup () {

    return
    root_ThreadGroup(Thread.currentThread().getThreadGroup()); }

  //----------------------------------------------------------
  /** @return an {@link Thread}<code>[]</code> of all the
   ** threads in <code>group</code> or any of its descendants.
   **/

  public static final Thread[]
  get_threads (final ThreadGroup group) {

    // api doc says activeCount is an 'estimate'
    final int m = 2*group.activeCount();
    final Thread[] threads = new Thread[m];
    group.enumerate(threads);
    return threads; }

  /** @return an {@link Thread}<code>[]</code> of all the
   ** threads under the root ancestor {@link ThreadGroup}
   ** of the current thread.
   **/

  public static final Thread[]
  get_threads () {

    return get_threads(root_ThreadGroup()); }

  //----------------------------------------------------------
  /** @return a {@link String} listing as many
   ** {@link Thread}s as possible, one per line,
   ** ending with a new line.
   **/

  public static final String
  list_threads () {

    final Thread[] threads = get_threads();
    final int n = threads.length;
    final StringBuffer b = new StringBuffer(n*32);
    final String nl = System.getProperty("line.separator");
    for (int i=0;i<n;i++) {
      if (null != threads[i]) {
        b.append(i);
        b.append(": ");
        b.append(threads[i].toString());
        b.append(nl); } }

    return b.toString(); }

  //----------------------------------------------------------
  /** Print a thread list, for debugging. **/

  public static final void
  print_threads (final java.io.PrintWriter pw) {

    pw.println();
    pw.println("In " + Thread.currentThread() + ":");

    pw.print(list_threads());

    pw.flush(); }

  //----------------------------------------------------------
  /** Print a stack trace, for debugging. **/

  public static final void
  print_threads (final java.io.OutputStream s) {

    print_threads(new java.io.PrintWriter(s)); }

  //==========================================================
  } // end class
  //==========================================================
(Review ID: 120441) 
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mustang
25-09-2004

WORK AROUND Name: boT120536 Date: 04/11/2001 Ensure JFileChooser's selected file and current directory are consistent. ======================================================================
25-09-2004

EVALUATION Still reproducible in 1.5.0. ###@###.### 2004-09-03
03-09-2004