类加载器public abstract class ClassLoader 解说:它是抽象类,不能直接用。可使用其子类如urlclassloader。
其有两个重要方法:
loadclass类加载顺序
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { // First, check if the class has already been loaded Class c = findLoadedClass(name); if (c == null) { try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClass0(name); } } catch (ClassNotFoundException e) { // If still not found, then invoke findClass in order // to find the class. c = findClass(name); } } if (resolve) { resolveClass(c); } return c; }
findClass需要子类实现:用于加载具体的类,如类路径等
protected Class<?> findClass(String name) throws ClassNotFoundException { throw new ClassNotFoundException(name); }
一、 URLClassLoader cl1=new URLClassLoader(urls, null); 说明?自定义ClassLoader可以使用现成的URLClassLoader指定parent为null,
new URLClassLoader(urls, null) =》
URLClassLoader的super(parent);=》
SecureClassLoader的super(parent);=》
ClassLoader的this.parent = parent;
所以最后会将ClassLoader的parent为null。
所以加载器还是会先从bootStrap中加载类。但不会从ext、app中加载。见以上第9行。
另外即使不赋为null,那parent->parent->....最后一定会有一个为null,即还是会执行到第9行。
这样好处是:自己写的类加载器不会将JRE的核心类覆盖掉。
二、 自定义ClassLoader可以使用现成的URLClassLoader且可以指定parent为null,为什么有时还要自己写呢?
虽然可以复用URLClassLoader,但其还是使用classloader的loadClass方法,即流程没变,如果要改变类加载顺序必须重写。
场景一:
应用的ClassLoader里面加载了1,2,3,4,5个JAR包。
自己的ClassLoader想共享应用的1,2,3,4的JAR包,但不想用5的JAR,这时要自己要在里面排除5,可根据包名。
场景二:
1.当系统要集成两个开源框架,而这两个框架使用了POI的两个版本的包、2.或者将新框架集成到现有系统时,有包版本冲突
这时可写自己的类加载器,分别加载不同的版本包