一、类的加载过程
Java类(.java)—> 字节码⽂件(.class) —> 字节码⽂件需要被加载到JVM内存当中。
二、类加载器(ClassLoader)
类加载器(ClassLoader)也是⼀个类,jvm启动的时候先把类加载器读取到内存当中去,再去加载其他的类,⽐如各种jar中的字节码⽂件,⾃⼰开发的代码编译之后的.class⽂件等等。
三、JVM 的类加载机制
JVM 的类加载机制中有⼀个⾮常重要的⻆⾊叫做类加载器(ClassLoader),类加载器有⾃⼰的体系,JVM 内置了⼏种类加载器,包括:引导类加载器、扩展类加载器、系统类加载器,他们之间形成⽗⼦关系,通过 Parent 属性来定义这种关系,最终可以形成树形结构。
类加载器 | 作⽤ |
引导启动类加载器 BootstrapClassLoader | c++编写,加载类库如rt.jar(Java核心类库),charsets.jar(字符集支持包),jce.jar(是一组包,它们提供用于加密、密钥生成和协商以及 Message Authentication Code(MAC)算法的框架和实现), jsse.jar(安全套接字拓展包Java(TM) Secure Socket Extension,net.properties(JVM网络配置信息) 没有父类 |
扩展类加载器 ExtClassLoader | java编写,加载扩展库 JAVA_HOME/lib/ext⽬录下的jar 中的类,如classpath中的jre ,javax.*或者java.ext.dir 指定位置中的类 父类为BootstrapClassLoader |
系统类加载器SystemClassLoader | 父类为ExtClassLoader |
另外:⽤户可以⾃定义类加载器(Java编写,⽤户⾃定义的类加载器,可加载指定路径的 class ⽂件)
当 JVM 运⾏过程中,⽤户⾃定义了类加载器去加载某些类时,会按照下⾯的步骤(⽗类委托机制)
1、⽤户⾃⼰的类加载器,把加载请求传给⽗加载器,⽗加载器再传给其⽗加载器,⼀直到加载器 树的顶层
2、最顶层的类加载器⾸先针对其特定的位置加载,如果加载不到就转交给⼦类
3 、如果⼀直到底层的类加载都没有加载到,那么就会抛出异常 ClassNotFoundException 因此,按照这个过程可以想到,如果同样在 classpath 指定的⽬录中和⾃⼰⼯作⽬录中存放相同的 class,会优先加载 classpath ⽬录中的⽂件
四、双亲委派机制
1、什么是双亲委派机制
当某个类加载器需要加载某个.class⽂件时,它⾸先把这个任务委托给他的上级类加载器,递归这个操作,如果上级的类加载器没有加载,⾃⼰才会去加载这个类
2、双亲委派机制的作⽤
1)防⽌重复加载同⼀个.class。通过委托去向上⾯问⼀问,加载过了,就不⽤再加载⼀遍。保证数据 安全。
2)保证核⼼.class不能被篡改。通过委托⽅式,不会去篡改核⼼.class,即使篡改也不会去加载,即使 加载也不会是同⼀个.class对象了。不同的加载器加载同⼀个.class也不是同⼀个.class对象。这样 保证了class执⾏安全(如果⼦类加载器先加载,那么我们可以写⼀些与java.lang包中基础类同名 的类, 然后再定义⼀个⼦类加载器,这样整个应⽤使⽤的基础类就都变成我们⾃⼰定义的类了。 )
Object类 -----> ⾃定义类加载器(会出现问题的,那么真正的Object类就可能被篡改了)