package com.zqh.classloader; /** * Created by zqhxuyuan on 15-2-28. */ import java.io.File; import java.io.FileFilter; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; /** * A parent-last classloader that will try the child classloader first and then * the parent. */ public class DirectoryBasedParentLastURLClassLoader extends ClassLoader { private ChildURLClassLoader childClassLoader; /** * This class delegates (child then parent) for the findClass method for a * URLClassLoader. Need this because findClass is protected in * URLClassLoader */ private class ChildURLClassLoader extends URLClassLoader { private ClassLoader realParent; public ChildURLClassLoader(URL[] urls, ClassLoader realParent) { // pass null as parent so upward delegation disabled for first // findClass call super(urls, null); this.realParent = realParent; } @Override public Class<?> findClass(String name) throws ClassNotFoundException { try { // first try to use the URLClassLoader findClass return super.findClass(name); } catch (ClassNotFoundException e) { // if that fails, ask real parent classloader to load the // class (give up) return realParent.loadClass(name); } } } public DirectoryBasedParentLastURLClassLoader(String jarDir) { super(Thread.currentThread().getContextClassLoader()); // search for JAR files in the given directory FileFilter jarFilter = new FileFilter() { public boolean accept(File pathname) { return pathname.getName().endsWith(".jar"); } }; // create URL for each JAR file found File[] jarFiles = new File(jarDir).listFiles(jarFilter); URL[] urls; if (null != jarFiles) { urls = new URL[jarFiles.length]; for (int i = 0; i < jarFiles.length; i++) { try { urls[i] = jarFiles[i].toURI().toURL(); } catch (MalformedURLException e) { throw new RuntimeException( "Could not get URL for JAR file: " + jarFiles[i], e); } } } else { // no JAR files found urls = new URL[0]; } childClassLoader = new ChildURLClassLoader(urls, this.getParent()); } @Override protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { try { // first try to find a class inside the child classloader return childClassLoader.findClass(name); } catch (ClassNotFoundException e) { // didn't find it, try the parent return super.loadClass(name, resolve); } } }