JVM之类加载与双亲委派
系统加载Class类型的文件主要三步:加载->连接->初始化。连接又可以分为三步:*验证->准备->解析
类加载过程描述
类加载过程完成的事情:
- 通过全类名获取定义此类的二进制字节流
- 将字节流所代表的静态存储结构转为方法区的运行时数据结构
- 在内存中生成一个代表该类的Class对象,作为方法区这些数据的访问入口
类加载器
java中内置了三个重要的ClassLoader
- BootstrapClassLoader(启动类加载器):最顶层的加载类,负责加载%JAVA_HOME%/lib目录下的 jar 包和类;
- ExtensionClassLoader(扩展类加载器):主要负责加载目录%JRE_HOME%/lib/ext 目录下的 jar 包和类;
- AppClassLoader(应用程序类加载器):面向用户的加载器,负责加载当前应用calsspath下所有的jar包和类
双亲委派模型
介绍
每一个类都有一个对应的类加载器。系统中的类加载器在协同工作的时候会默认使用双亲委派模型。即在类加载的时候,系统会首先判断当前类是否被加载过,以及被加载的类会直接返回,否则才会尝试加载。加载的时候首先会把该请求委派该父类加载器的loadClass()处理,因此所有的请求最终都会传送到顶层启动类加载器BootstrapClassLoader中。当父类加载器无法处理,才会由自己处理。当父类加载器为null,会使用BootstrapClassLoader作为父类加载器。
当一个类加载器收到了类加载的请求的时候,他不会直接去加载指定的类,而是把这个请求委托给自己的父加载器去加载。只有父加载器无法加载这个类的时候,才会由当前这个加载器来负责类的加载
实现
- 先检查类是否已经被加载过
- 若没有加载则调用父加载器的loadClass()方法进行加载
- 若父加载器为空则默认使用启动类加载器作为父加载器。
- 如果父类加载失败,抛出ClassNotFoundException异常后,再调用自己的findClass()方法进行加载。
双亲委派模型的优点
- 避免类的重复加载
- 避免核心类被不同类加载器加载产生冲突,保证核心库的安全
如何打破双亲委派模型
不仅要继承ClassLoader类,还要重写loadClass和findClass方法。如果不想打破,重写ClassLoader 类中的 findClass() 方法即可,无法被父类加载器加载的类最终会通过这个方法被加载。
loadClass() 就是主要进行类加载的方法,默认的双亲委派机制就实现在这个方法中。
findClass() 根据名称或位置加载.class字节码
Enjoy Reading This Article?
Here are some more articles you might like to read next: