Adds shutdown hook in DiskCache

The RandomAccessFile must be closed otherwise it prevents
the temp file to be deleted on Windows.

Bug: #9587
Bug-Link: https://github.com/gwtproject/gwt/issues/9587
Change-Id: I0a1efd7d7a0f4ea846a4cb7d730c0c153628e8bc
diff --git a/dev/core/src/com/google/gwt/dev/util/DiskCache.java b/dev/core/src/com/google/gwt/dev/util/DiskCache.java
index 2378fe1..62a5aeb 100644
--- a/dev/core/src/com/google/gwt/dev/util/DiskCache.java
+++ b/dev/core/src/com/google/gwt/dev/util/DiskCache.java
@@ -49,7 +49,7 @@
   public static DiskCache INSTANCE = new DiskCache();
 
   private boolean atEnd = true;
-  private RandomAccessFile file;
+  private final RandomAccessFile file;
 
   private DiskCache() {
     try {
@@ -57,6 +57,7 @@
       temp.deleteOnExit();
       file = new RandomAccessFile(temp, "rw");
       file.setLength(0);
+      registerShutdownHook();
     } catch (IOException e) {
       throw new RuntimeException("Unable to initialize byte cache", e);
     }
@@ -233,4 +234,25 @@
       return position;
     }
   }
-}
\ No newline at end of file
+
+  /**
+   * Register a shutdown hook to close the RandomAccessFile associated with the temp file.<br>
+   * There is a known <a href="https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4171239">bug</a>
+   * in Windows that prevents the 'temp' file from being deleted by 'deleteOnExit'
+   * (see {@link DiskCache#DiskCache()}) because it is still open by the RandomAccessFile.<br>
+   * This hook forces the RandomAccessFile to be closed at shutdown to allow the correct
+   * 'temp' file removal.
+   */
+  private void registerShutdownHook() {
+    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          file.close();
+        } catch (IOException e) {
+          // No exception handling in a shutdown hook
+        }
+      }
+    }));
+  }
+}