Java File.deleteOnExit()无法正常运行Windows 10

时间:2015-09-22 06:18:08

标签: java

我试图为jar文件编写代码,如果执行该代码,它会关闭JVM然后删除jar文件。这是我到目前为止所做的尝试,但是在JVM关闭后它没有删除文件。

    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;
}

有人可以解释为什么deleteOnExit在这个实例中不起作用吗?

1 个答案:

答案 0 :(得分:1)

确保在退出JVM之前关闭已在文件上打开的任何流。否则,在Windows上无法触发应该删除文件的关闭挂钩,因为打开流会触发操作系统级别的文件锁定。

对于您的示例,这意味着您在退出try-with-ressources-block之前不得结束JVM进程,该块大致翻译为:

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

当你的程序在执行finally块之前退出时,会在不关闭流的情况下触发关闭挂钩,并且无法删除该文件。

请注意,以下代码可用于您的目的,因为在关闭try-with-ressources参数后执行finally块:

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