Jonathan Beaudoin
Jonathan Beaudoin

Reputation: 2188

Java File.deleteOnExit() not working Windows 10

I'm trying to write code for a jarfile which if executed, it shutdowns the JVM and then deletes the jarfile. This is what I've tried to do so far but it is not deleting the file after the JVM closes.

    public static void check() {
    if (isJarFile()) {
        try (Scanner s = new Scanner(new URL(HASH_PROVIDER).openStream())) {
            String remote_hash = s.nextLine().trim();
            File jarFile = getJarFile();
            if (jarFile != null && !remote_hash.equals(getMD5Checksum(jarFile.getAbsolutePath()))) {
                jarFile.setWritable(true);
                jarFile.deleteOnExit();
            }
            System.exit(0);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(0);
        }
    }
}

public static byte[] createChecksum(String filename) throws Exception {
    InputStream fis = new FileInputStream(filename);
    byte[] buffer = new byte[1024];
    MessageDigest complete = MessageDigest.getInstance("MD5");
    int numRead;
    do {
        numRead = fis.read(buffer);
        if (numRead > 0) {
            complete.update(buffer, 0, numRead);
        }
    } while (numRead != -1);
    fis.close();
    return complete.digest();
}

public static String getMD5Checksum(String filename) throws Exception {
    byte[] b = createChecksum(filename);
    String result = "";
    for (int i = 0; i < b.length; i++) {
        result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
    }
    return result;
}

public static File getJarFile() {
    try {
        return new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
    } catch (URISyntaxException e) {
        e.printStackTrace();
    }
    return null;
}

Can someone explain why deleteOnExit is not working in this instance?

Upvotes: 1

Views: 3520

Answers (1)

Rafael Winterhalter
Rafael Winterhalter

Reputation: 44042

Make sure that you close any stream that you have open on a file before exiting your JVM. Otherwise, the shut down hook that is supposed to delete the file cannot trigger on Windows as opening the stream triggers a file lock on the OS-level.

For your example, it means that you must not end the JVM process before exiting the try-with-ressources-block which is roughly translated into:

Scanner s = new Scanner(new URL(HASH_PROVIDER).openStream())
try {
  // your code
  System.exit(0);
} finally {
    s.close(); // Never executed
}

As your program exits before the finally block is executed, the shut down hook is triggered without closing the stream and the file cannot be deleted.

Note that the following code will work for your purposes as the finally block is executed after closing the try-with-ressources argument:

try (Scanner s = new Scanner(new URL(HASH_PROVIDER).openStream())) {
  // your code
} catch (Exception e) {
  e.printStackTrace();
} finally {
  System.exit(0);
}

Upvotes: 2

Related Questions