Java-Process可以删除加载的JAR吗?

时间:2010-10-22 14:40:54

标签: java jar classloader delete-file

您好我有以下问题:

在卸载过程中,我加载了一个JAR(jdbc-driver)。

    URL pDriverJar = jarToDelete.toURI().toURL();
    URL[] lURLList = new URL[]{pDriverJar};
    URLClassLoader lLoader =  new URLClassLoader(lURLList, Thread.currentThread().getContextClassLoader());
    Thread.currentThread().setContextClassLoader(lLoader);
    Class<?> aClass = Class.forName("jdbc.Driver"); // was Oracle: oracle.jdbc.OracleDriver but should not be important

    if(jarToDelete.delete()){
        System.out.println("deleted");
    }else {
        jarToDelete.deleteOnExit();
    }

终止JVM后,jar仍然存在。

作为一个workarround,我创建了一个临时文件,并将Jar复制到该tempfile。但现在不会删除Tempfile。

我读过,如果ClassLoad是GC,可以删除加载的jar。

有没有人有想法,如何删除此文件?

3 个答案:

答案 0 :(得分:5)

这取决于操作系统。 Windows不允许您删除正在使用的文件,但Linux会删除。

一种解决方案是启动第二个进程,等待你的JVM死掉,然后删除文件,因为即使你清除所有对使用它的类加载器的引用,也不能保证它们会释放文件。没有办法强制对象的垃圾收集(甚至完成)。

另一个解决方案是编写加载Jar的类加载器。这样,当你想要摆脱它时,你可以确定Jar是关闭的。如果打开它的唯一对象是你的类加载器,那么你可以确定它是免费的并且应该是可删除的。

答案 1 :(得分:2)

此问题已在Java 7中修复;使用close()类中的ClassLoader方法。对于旧版本,有几种选择:

  • 编写自定义类加载器,例如like this

  • 使用反射并关闭所有JarFile个实例;它们位于sun.misc.URLClassPath

答案 2 :(得分:0)

由于我想杀死java11所需的类路径上的jar文件,但导致Java 1.8或更低版本出现问题;我使用的一种解决方案,而无需启动另一个进程来杀死jar文件,只是通过

将文件设置为0个字节。
FileOutputStream out = new FileOutputStream(f);
out.write(new byte[0]);
out.flush(); out.close();

然后,即使0字节文件仍在清单中,应用程序下次启动该代码后仍设法将其删除:

if (f.exists()){
    if (f.delete() == false) f.deleteOnExit();
}