JVM笔记1
1、代码是怎么运行起来的?
-
Java代码文件编译成".class"后缀的字节码文件
-
类加载器会把编译好的字节码文件加载到JVM中去
-
JVM基于自己的字节码执行引擎,执行加载到内存中的类
2、类加载过程?
- 加载 -> 验证 -> 准备 -> 解析 -> 初始化
- 加载: 类加载器会把编译好的字节码文件加载到JVM。
- 验证: 根据Java虚拟机规范,验证加载的".class"文件内容是否符合规范。
- 准备: 给类以及类静态变量、属性等分配一定的内存空间,赋予初始化0或null。
- 解析:将常量池中符号引用替换成直接引用。
- 初始化:核心阶段,针对类静态变量、属性等号(=)后代码的执行以及对静态代码块的代码执行。
3、JVM什么情况下初始化一个类?
- 类实例创建:new创建实例对象、反射生成类实例对象等,而不是main函数启动或spring启动时初始化。
- main方法依赖:main函数启动时即创建。
- 子类初始化:初始化类的过程中,若发现该类的父类未初始化,那么会先初始化父类,然后再初始化该类。
4、类加载器
4.1 启动类加载器
BootStrap ClassLoader,Jvm启动的时候,首先会依托类加载器去加载我们在机器上安装在Java目录下lib文件夹的核心类。
4.2 扩展类加载器
Extension ClassLoader,Java目录下lib/ext文件夹的类需要该类加载器去加载,来支撑系统的运行。
4.3 应用类加载器
Application ClassLoader,负责加载“ClassPath”环境变量路径下的所指定的类,也就是我们写的Java代码类。
4.4 自定义类加载器
除以上类以外,根据自己需求自定义类的加载器。
5、双亲委派模型
5.1 什么叫双亲委派模型?
Java的类加载器是存在层级结构的,结构如下图:
-
基于这个层级结构,我们来了解一个重要概念:双亲委派模型
核心:向上委派,父类优先加载,否则下推加载权利给子类
-
当Java虚拟机需要加载一个User类,此时应用类加载器不会自己去加载该类,而是会咨询父类(扩展类加载器)可否加载?
-
扩展类收到咨询后也不会去加载该类,而是咨询父类(启动类加载器)可否加载?
-
启动类加载器收到后,如果能加载就会加载该User类。若不能加载,就会下推加载权利给子类,也就是扩展类加载器。
-
扩展类加载器收到加载权利后,若能加载User类就会启动加载,若不能加载也会继续下推加载权利到子类,也就是应用类加载器,从而让应用类加载器启动加载该User类。
5.2 双亲委派模型的好处?
- 避免同一类重复加载:因为类加载是向上委托的,确保了一个类只会被加载一次
- 避免Java的核心Api被篡改:父类以及加载过了,自定义的类已经不起作用了,有一定的安全性。
5.3 tomcat需要破坏双亲委派模型的原因?
-
tomcat中的需要支持不同web应用依赖同一个第三方类库的不同版本,jar类库需要保证相互隔离;
-
同一个第三方类库的相同版本在不同web应用可以共享
-
tomcat自身依赖的类库需要与应用依赖的类库隔离
-
需要支持jsp修改后不用重启tomcat即可生效,为了上面类加载隔离和类更新不用重启,定制开发各种的类加载器