类加载过程
- 加载:在硬盘上查找并通过IO读入字节码文件,使用到类时才会加载
补充:使用到类时才会加载这个是针对用户写的类,而支撑jvm运行的一些类比如java.lang包下的类是启动的时候就已经加载到jvm中
- 验证:校验字节码文件的正确性
比如以下字节码文件:
如果手动修改这个字节码文件,则校验会报错
- 准备:给类的静态变量分配内存,并赋予默认值
其中initData变量的默认值为0
- 解析:将符号引用替换为直接引用
该阶段会把一些静态方法(符号引用,比如main()方法)替换为指向数据所存内存的指针或句柄等
- 初始化:对类的静态变量初始化为指定的值,执行静态代码块
在准备阶段已经将initData变量赋值默认值0,初始化则是将initData变量赋值为代码中所写的666变量值
类加载器
- 应用程序类加载器:负责加载ClassPath路径下的类包,主要就是加载你自己写的那些类
双亲委派机制
双亲委派机制说简单点就是,先找父亲加载,不行再由儿子自己加载
查看源码:发现如果有父类ClassLoader那么就会调用父类ClassLoader的loadClass
为什么要设计双亲委派机制?
- 沙箱安全机制:自己写的java.lang.String.class类不会被加载,这样便可以防止核心API库被随意篡改
- 避免类的重复加载:当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次,保证被加载类的唯一性
Tomcat打破双亲委派机制
1、比如tomcat下有两个应用程序,一个用spring4版本的,另一个用spring5版本的,那么两个应用程序的spring肯定是由很多类名是一样的,那么就需要隔离两个应用程序,打破双亲委派的机制
2、比如像servlet.jar这样的公用的jar包,如果有10个应用程序部署,那么它们将使用同一份同版本的servlet.jar,打破双亲委派机制
3、比如tomcat下有两个应用程序,一个有自己的一个依赖jar包,另一个不希望有这个依赖包,打破双亲委派机制
自定义类加载器打破双亲委派机制
需要去掉双亲委派相关代码
沙箱安全机制
在自定义类加载器路径中添加java.lang.String类
则会抛出包名禁止异常