类加载器和双亲委派机制

88 阅读2分钟

类加载过程

加载 -> 连接 -> 初始化

连接:验证 -> 准备 -> 解析

加载的三个作用:

  1. 通过全类名获取定义此类的二进制的字节流
  2. 字节流所代表的静态存储结构转化为方法区的运行时数据结构
  3. 在内存中生成代表该类的Class对象
数组类型不通过类加载器创建,而是由JVM直接创建

JVM中的类加载器(ClassLoader)

1.BootStrapClassLoader 启动类加载器

  • 最顶层的加载器,由C++实现。加载%java_home%lib目录下,jar包和类或者被-XbootClasspath参数指定的路径中所有的类。常用的String、Float等都在这个类加载器中加载

2.ExtensionClassLoader 扩展类加载器

  • 加载%jre_home%/lib/ext目录下jar包和类

3.AppClassLoader 应用程序类加载器

  • 面向用户的类加载器,加载当前classpath下所有的jar包和类

双亲委派

每个类都有一个对应类加载器,系统中ClassLoader在协同工作时,会默认使用双亲委派模型。即在类加载的时候,系统会先判断,当前类是否被加载过。已经被加载的类会直接返回,否则尝试加载。加载的时候,会先把该请求委派给父类加载器的LoadClass()处理,因此所有请求最终都应该传送到顶层的启动类加载器的BootStrapClassLoader中。当父类加载器无法处理的时候,才由自己来处理。当父类加载器为null时,会使用启动类加载器BootStrapClassLoa作为父类加载器。

  1. 自底向上检查是否被加载
  2. 自顶向下尝试加载

作用:

保证了Java程序的稳定运行,避免类的重复加载。

JVM区分不同的类,不仅仅是靠类名,相同的类文件被不同的类加载器加载会产生两个不同的类 。如果不用双亲委派机制,而每个类加载器加载自己的话,会出现一些问题:比如两个Object类,那么程序运行会产生不同的Object类

不想用双亲委派机制

自定义一个类加载器,然后重载loadClass()

如何自定义类加载器?

类加载器除了BootStrapClassLoader以外,全部由Java实现,且继承了ClassLoader。那么由此可见,自定义类加器也必须继承ClassLoader。