Java virtual machine
jvm跟class无关。任何语言只要能遵循class的规范,一样能被jvm 运行。
jdk、jre、jvm的关系
class 文件查看
IDEA --> setings --> BinEd 二进制/十六进制转化
jclasslib bytecode
官网下载插件地址
https://plugins.jetbrains.com/
class 文件内容:
magic : 文件标识符,cafe babe :class 文件。2字节
minor version : 小版本标识符 。例如 52.0,后面的 .0
major version: 大版本标识符。例如52.0,就是52
constant_poolc 常量池常量数量,最大可存放 2个字节 65535个。常量池从1开始。
super class:父类class 文件
access_flags:访问修饰符、是否接口或抽象类等
this class
fields count
methods count:有多少个方法
interfaces count:实现了多少个接口
attributes count
Java默认混合模式(解释器+热点代码编译)
java 代码class 需要通过Java 解释器进行执行。
检测热点代码:-XX:CompileThreshold = 10000
-Xmixed 默认混合模式 -Xint 编译模式,启动快执行慢 -Xcomp 编译模式,执行快启动慢
1. Loading
2. Linking
1. Verification
1. 验证文件是否符合JVM规定
2. Preparation
1. 静态成员变量赋默认值
3. Resolution
1. 将类、方法、属性等符号引用解析为直接引用
常量池中的各种符号引用解析为指针、偏移量等内存地址的直接引用
3. Initializing
1. 调用类初始化代码 <clinit>,给静态成员变量赋初始值
类加载器
通过 System.out.println(String.class.getClassLoader()); 来查看使用的加载器
根类加载器(bootstrap class loader):负责加载java基础类,主要是 %JRE_HOME/lib/ 目录下的rt.jar、resources.jar、charsets.jar和class等
扩展类加载器(extensions class loader):负责加载java扩展类,主要是%JRE_HOME/lib/ext 目录下的jar和class
根据类路径来加载java类:AppClassLoader:负责加载当前java应用的classpath中的所有类
Custom ClassLoader(自定义ClassLoader)
自定义加载的三种方式:
findClass 定义查找Class的方式
defineClass 将类文件字节码加载为jvm中的class
findResource 定义查找资源的方式
向上加载,而不是向上继承。 即 AppClassLoader 加载不到的时候交给 extensions class loader 加载,而不是继承。
loading 的过程是 双亲委派:
父加载器:父加载器不是“类加载器的加载器”!
双亲委派是一个孩子向父亲方向,然后父亲向孩子方向委派过程。
当一个自定义app 类,自定义加载器 Custom ClassLoader 发现没有加载,向父加载器 AppClassLoader 查找,没有继续向上,一直到 bootstrapclassloader,这其中发现有的话就返回,如果一直没有,就由 bootstrapclassloader 向下委派,一直到自定义加载去加载到内存中。
为什么要用双亲委派,因为安全问题。
钩子函数、模板方法(设计模式)
当加载某个类时,先调用父加载器加载 parent.loadClass ,一直往上,加载不到再调用自己的 findClass 方法进行加载。
如何打破双亲委派:重写loadClass()