I played with classLoaders in Java and noticed a strange thing. If classLoader loads a class from jar, this bank is blocked indefinitely, even if you do not reference classLoader.
In the example below, jar contains the HelloWorld class. I am trying to load a class contained in a jar using classLoader which dynamically adds a jar. If you set skip to true and do not call Class.forName , you can delete the jar, but if you don't skip and even if you don't reference classLoader ( classLoader = null ), the jar cannot be deleted until the JVM exits.
Why is this?
PS: I am using java 6 and the code is very verbose for testing purposes
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, 0, len); } finput.close(); foutput.close(); return true; } } public boolean deleteJar() { File destJar = new File("C:\\Users\\Adel\\Desktop\\classes.jar"); return destJar.delete(); } }
java classloader urlclassloader
Adel boutros
source share