Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-7177673

(fc) Asynchronous close of FileChannel can take a long time when threads are blocked [win]

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: P4
    • Resolution: Won't Fix
    • Affects Version/s: 7
    • Fix Version/s: None
    • Component/s: core-libs
    • Labels:
    • Subcomponent:
    • Introduced In Version:
    • CPU:
      x86
    • OS:
      windows_7

      Description

      FULL PRODUCT VERSION :
      java version "1.7.0_05"
      Java(TM) SE Runtime Environment (build 1.7.0_05-b05)
      Java HotSpot(TM) 64-Bit Server VM (build 23.1-b03, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      Calling interrupt() stalls the current thread if the interrupted thread is waiting for a FileChannel operation to complete. The reason is that interrupt() also closes the FileChannel and therefore has to wait until all I/O operations have actually stopped.

      This is a serious issue in GUI applications: If a SwingWorker is performing I/O in the background, calling SwingWorker.cancel(true) in the Event Dispatch Thread can freeze the GUI for a while.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Create a large file (preferably on a "slow" drive, e.g., a network share).
      2. In a background thread, use a FileChannel to copy this file.
      3. interrupt() the background thread.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      interrupt() returns immediately
      ACTUAL -
      interrupt() takes several seconds to complete

      REPRODUCIBILITY :
      This bug can be reproduced often.

      ---------- BEGIN SOURCE ----------
      class Copier extends Thread {
      final String src, dest;

      Copier(String src, String dest) {
      this.src = src;
      this.dest = dest;
      }

      @Override
      public void run() {
      try (FileInputStream in = new FileInputStream(src);
      FileOutputStream out = new FileOutputStream(dest)) {
      transfer(in.getChannel(), out.getChannel());
      } catch (Exception e) {
      e.printStackTrace();
      }
      }

      void transfer(FileChannel in, FileChannel out) throws IOException {
      long transferred = 0;
      long length = 0;
      do {
      transferred += length;
      length = out.transferFrom(in, transferred, 64 << 20);
      } while (length > 0);
      }
      }

      public class ChannelInterruptTest {
      public static void main(String[] args) throws Exception {
      Copier copy = new Copier("\\\\someserver\\someshare\\input.dat",
      "\\\\someserver\\someothershare\\output.dat");
      copy.start();
      Thread.sleep(5000);

      System.out.println("interrupting");
      long start = System.currentTimeMillis();
      copy.interrupt();
      long stop = System.currentTimeMillis();
      System.out.println((stop - start) + "ms");
      }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Do not call interrupt() directly. Instead, spawn a new thread which calls interrupt().

        Attachments

          Activity

            People

            • Assignee:
              alanb Alan Bateman
              Reporter:
              webbuggrp Webbug Group
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Imported:
                Indexed: