目录
重要的结论:
- ClassLoader的主要作用是通过类的全限定名如:com.yej.learning.entity.User,找到相应的class字节码内容,然后得到java运行空间内存中的Class对象;
- 不同的ClassLoader的方法 Class<?> loadClass(String name)不同,主要通过Class<?> findClass(String name)方法的不同实现;
- AppClassLoader、ExtClassLoader都是sun.misc.Launcher的内部类,bootStrap class loader加载类是native方法实现的;
- AppClassLoader的parent为ExtClassLoader,ExtClassLoader 的parent为null;
- 自己开发的类的通过AppClassLoader完成的加载;
- 类加载的双亲委派机制:一个ClassLoader收到loadClass请求时总是先调用parent进行类加载,parent无法完成类加载时再调用bootStrap class loader进行类加载,当parent和bootStrap class loader都无法完成类加载时自己才进行类加载。
JAVA中的三个classLoader及其类加载路径
获取各个类加载器的加载路径源码:
package com.yej.learning;
import sun.misc.Launcher;
import java.net.URL;
import java.net.URLClassLoader;
public class ClassLoaderLoadPath {
public static void main(String[] args) {
System.out.println("BootstrapClassLoader 的加载路径: ");
URL[] urls = Launcher.getBootstrapClassPath().getURLs();
for (URL url : urls) {
System.out.println(url);
}
System.out.println("----------------------------");
//获得ExtClassLoader
URLClassLoader extClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader().getParent();
System.out.println(extClassLoader);
System.out.println("ExtClassLoader 的加载路径: ");
URL[] extUrls = extClassLoader.getURLs();
for (URL url : extUrls) {
System.out.println(url);
}
System.out.println("----------------------------");
//获得AppClassLoader
URLClassLoader appClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
System.out.println(appClassLoader);
System.out.println("AppClassLoader 的加载路径: ");
URL[] appUrls = appClassLoader.getURLs();
for (URL url : appUrls) {
System.out.println(url);
}
System.out.println("----------------------------");
}
}
执行结果:
类加载的双亲委派机制
一个ClassLoader收到loadClass请求时总是先调用parent进行类加载,parent无法完成类加载时再调用bootStrap class loader进行类加载,当parent和bootStrap class loader都无法完成类加载时自己才进行类加载。
类加载源码分析
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
/**
***parent不为空时调用parent进行类加载
**/
c = parent.loadClass(name, false);
} else {
/**
***parent为空时调用bootStrap class loader进行类加载
**/
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
/**
***当parent和bootStrap class loader都无法完成类加载时才自己尝试进行类加载
**/
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}