Class类的实例表示正在运行的Java应用程序中的类或接口. Class类没有公共构造函数,那他是如何建立的呢? 咱们来看看官方文档是如何说的java
Instead {@code Class} objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the {@code defineClass} method in the class loader.c++
Class对象是由Java虚拟机在加载类时自动构造的,并经过调用类加载器中的defineClass方法来构造. 每一个Class对象包含一个定义他的类加载器的引用.jvm
private final ClassLoader classLoader;
函数
下面咱们就来认识一下类加载器.this
看看jdk文档怎么说:spa
A class loader is an object that is responsible for loading classes.Given the binary name of a class, a class loader should attempt to locate or generate data that constitutes a definition for the classdebug
类加载器是负责加载类的对象,给定一个类的全限定名,类加载应该尝试生成包含在类定义里面的数据流 通俗点解释就是: .java文件编译后生成.class文件, 类加载器就是将.class文件转换成java.lang.Class类的一个实例3d
负责加载系统类,由c语言实现,没有对应的类加载器 加载路径: System.getProperty("sun.boot.class.path");
code
负责加载扩展类 加载路径 System.getProperty("java.ext.dirs");
cdn
从用户类路径下加载 加载路径 System.getProperty("java.class.path");
System.out.println(String.class.getClassLoader()); // 加载系统类用到的类加载器
System.out.println(Student.class.getClassLoader()); // Student是用户自定义的类
复制代码
输出一下查看结果
null
sun.misc.Launcher$AppClassLoader@18b4aac2
复制代码
由于String是系统类,因此由BootstrapClassLoader加载,而BootstrapClassLoader没有对应的类加载器,因此为null
Student是在用户类路径下定义的,因此是由AppClassLoader加载
除了启动类加载器外,全部的类加载器都有一个父类加载器。类加载器要先把加载类的机会交给他的父类加载器。在父类加载器加载失败时,他才会加载该类
类加载器层次结构图:
加载Studeng类的过程: AppClassLoader先交给其父类ExtentsionClassLoader加载,ExtensionClassLoader交给他的父类BootstrapClassLoader加载,BootstrapClassLoader没有父类加载器,尝试加载,加载失败,让其子类ExtensionClassLoader加载,一样加载失败,交给其子类AppClassLoader加载,加载成功!
Launcher类是java应用的入口,由JVM建立的,源码对外隐藏,只能经过反编译查看. 为何Launcher类是java应用的入口? 由于 ApplicationClassLoader和ExtClassLoader都是在Launcher类定义的
ClassLoader类的loadClass()方法
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// 加锁机制
synchronized (getClassLoadingLock(name)) {
// 给定一个类的全限定名,检查类是否被加载过,底层调用的c++方法,不须要深刻研究
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
// 先让其父类加载
if (parent != null) {
c = parent.loadClass(name, false);
} else {
// 父类为空,则让BootStrapClassLoader加载该类
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
}
if (c == null) {
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;
}
}
复制代码
你们本身都debug几遍,就能搞懂双亲委派机制的流程,我就不贴图了,求关注
关注公众号,免费领取优秀jvm入门书籍