一、类加载器简介:
JVM启动时,会形成由三个类加载器组成的初始类加载器层次结构:
- Bootstrap ClassLoader:根类加载器,也称为引导或原始类加载器。它负责加载Java的核心类。它比较特殊,不是ClassLoader的子类,而是由JVM自身实现的。
- Extension ClassLoader:扩展类加载器。它负责加载JRE的扩展目录(JAVA_HOME/jre/lib/ext 或者由 java.ext.dirs 系统属性指定的目录)中JAR的类包。通过这种方式,我们就可以为java扩展核心类以外的新功能,只要我们把自己开发的类打包成JAR文件,然后放入JAVA_HOME/jre/lib/ext 路径即可。
- System ClassLoader:系统(也称为应用)类加载器,。它负责在JVM启动时,加载来自命令java中的-classpath选项或java.class.path系统属性,或CLASSPATH环境变量所指定的JAR包和类路径。程序可以通过ClassLoader的静态方法getSystemClassLoader()获取该类加载器。如果没有特别指定,则用户自定义的类加载器都以该类加载器作为它的父加载器。
二、加载机制之双亲委派模型源码分析:
/**
* Loads the class with the specified <a href="#name">binary name</a>. The
* default implementation of this method searches for classes in the
* following order:
*
* <ol>
*
* <li><p> Invoke {@link #findLoadedClass(String)} to check if the class
* has already been loaded. </p></li>
*
* <li><p> Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method
* on the parent class loader. If the parent is <tt>null</tt> the class
* loader built-in to the virtual machine is used, instead. </p></li>
*
* <li><p> Invoke the {@link #findClass(String)} method to find the
* class. </p></li>
*
* </ol>
*
* <p> If the class was found using the above steps, and the
* <tt>resolve</tt> flag is true, this method will then invoke the {@link
* #resolveClass(Class)} method on the resulting <tt>Class</tt> object.
*
* <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override {@link
* #findClass(String)}, rather than this method. </p>
*
* <p> Unless overridden, this method synchronizes on the result of
* {@link #getClassLoadingLock <tt>getClassLoadingLock</tt>} method
* during the entire class loading process.
*
* @param name
* The <a href="#name">binary name</a> of the class
*
* @param resolve
* If <tt>true</tt> then resolve the class
*
* @return The resulting <tt>Class</tt> object
*
* @throws ClassNotFoundException
* If the class could not be found
*/
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) {
// 如果当前类加载器不是根类加载器,则委派父类去加载目标类
c = parent.loadClass(name, false);
} else {
// 如果当前类加载器已经是根类加载器,则由根类加载器去加载目标类
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.
// 如果所有父类加载器都没加载成功,则调用本身类加载器的findClass进行
// 类加载(自定义类加载器要实现该方法)
long t1 = System.nanoTime();
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;
}
}
网友评论