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 insun.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();
}
精彩评论