开发者

Can a loaded JAR be deleted by the Java-Process?

Hello I have following Problem:

Within an uninstall-process I load a JAR (jdbc-driver).

    URL pDriverJar = jarToDelete.toURI().toURL();
    URL[] lURLList = new URL[]{pDriverJar};
    URLClassLoader lLoader =  new URLClassLoader(lURLList, Thread.current开发者_如何学运维Thread().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();
    }

After terminiation of the JVM, the jar is still existant.

As a workarround, I've created a tempfile, and copied the Jar to that tempfile. But now the Tempfile will not be deleted.

I've read, that if the ClassLoad is GC, the loaded jars can be removed.

Does anyone have an Idea, how to delete this File?


It depends on the operating system. Windows will not let you delete files that are in-use, but Linux will.

One solution would be to start a second process that waits for your JVM to die and then deletes the file, as even if you clear all references to classloaders using it, there is no guarantee that they will release the file. There is no way to force garbage collection (or even finalization) of an object.

Another solution would be to write the classloader that loads the Jar. That way, when you want to get rid of it, you can be certain that the Jar is closed. If the only object that opened it was your classloader, then you can be certain it is free and should be deletable.


This issue was fixed in Java 7; use the close() method in the ClassLoader class. For older versions, there are several options:

  • Write a custom classloader, e.g. like this

  • Use reflection and close all JarFile instances; they reside in sun.misc.URLClassPath


As I wanted to kill off a jar-file on the classpath that I needed for java11 but led to problems in java 1.8 or below; A solution that I used, without having to start another process to kill the jar file, was to just make the file 0 bytes by

FileOutputStream out = new FileOutputStream(f);
out.write(new byte[0]);
out.flush(); out.close();

And next time the application starts this code then manages to delete it, even though the 0-byte-file is still in the manifest:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜