我正在玩
Java中的classLoaders并注意到一件奇怪的事情.如果classLoader从jar加载一个类,即使你没有引用你的classLoader,这个jar也会无限期地被锁定.
在下面的示例中,jar包含一个名为HelloWorld的类.我所做的是尝试通过classLoader加载jar中包含的类,该类动态地添加jar.如果将skip设置为true并且不调用Class.forName,则可以删除jar,但如果不跳过,即使不引用classLoader(classLoader = null),也不能删除jar,直到JVM退出.
这是为什么?
PS:我使用的是java 6,代码非常冗长,用于测试目的
package loader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; public class TestClassLoader { private URLClassLoader classLoader; public TestClassLoader() throws MalformedURLException,IOException { System.out.println("Copying jar"); if (copyJar()) { System.out.println("Copying SUCCESS"); performFirstCheck(); } else { System.out.println("Copying Failed"); } } public static void main(String[] args) throws IOException { System.out.println("Test started"); TestClassLoader testClassLoader = new TestClassLoader(); System.out.println("Bye!"); } public void performFirstCheck() throws IOException { System.out.println("Checking class HelloWorld does not exist"); if (!checkClassFound(TestClassLoader.class.getClassLoader(),false)) { System.out.println("Deleting jar"); deleteJar(); System.out.println("First Check SUCCESS"); performSecondCheck(); } else { System.out.println("First Check Failed"); } } private void performSecondCheck() throws IOException { System.out.println("Copying jar"); if (copyJar()) { System.out.println("Copying SUCCESS"); createClassLoaderAndCheck(); } else { System.out.println("Copying Failed"); } } private void createClassLoaderAndCheck() throws MalformedURLException { System.out.println("Creating classLoader"); createClassLoader(); System.out.println("Checking class HelloWorld exist"); if (checkClassFound(classLoader,true)) { System.out.println("Second Check SUCCESS"); classLoader = null; System.out.println("Deleting jar"); if (deleteJar()) { System.out.println("Deleting SUCCESS"); } else { System.out.println("Deleting Failed"); } } else { System.out.println("Second Check Failed"); } } public void createClassLoader() throws MalformedURLException { URL[] urls = new URL[1]; File classFile = new File("C:\\Users\\Adel\\Desktop\\classes.jar"); urls[0] = classFile.toURI().toURL(); classLoader = new URLClassLoader(urls); } public boolean checkClassFound(ClassLoader classLoader,boolean skip) { if (skip) { System.out.println("Skiping class loading"); return true; } else { try { Class.forName("HelloWorld",true,classLoader); return true; } catch (ClassNotFoundException e) { return false; } } } public URLClassLoader getClassLoader() { return classLoader; } public boolean copyJar() throws IOException { File sourceJar = new File("C:\\Users\\Adel\\Desktop\\Folder\\classes.jar"); File destJar = new File("C:\\Users\\Adel\\Desktop\\classes.jar"); if (destJar.exists()) { return false; } else { FileInputStream finput = new FileInputStream(sourceJar); FileOutputStream foutput = new FileOutputStream(destJar); byte[] buf = new byte[1024]; int len; while ((len = finput.read(buf)) > 0) { foutput.write(buf,len); } finput.close(); foutput.close(); return true; } } public boolean deleteJar() { File destJar = new File("C:\\Users\\Adel\\Desktop\\classes.jar"); return destJar.delete(); } }