字节码文件详解
字节码文件的组成
字节码文件本质上是一个二进制文件,无法直接用记事本等工具打开阅读器内容。需要通过专业的工具打开。
- 开发环境使用jclasslib插件。
- 服务器环境使用javap -v命令。
字节码文件:
- 基本信息:魔数Cafe babe、字节码文件对应的Java版本号、访问标识(public、final等)、父类和接口。
- 常量池:保存了字符串常量、类或接口名、字段名,主要在字节码指令中使用。
- 字段:当前类或接口声明的字段信息。名字、标识符(字段类型)、访问标识。前两指向常量池。
- 方法:当前类或接口声明的方法信息,字节码指令。方法信息包括:方法名、描述符(参数和返回值)、访问标识。
- 属性:类的属性,比如源码的文件名,内部类的列表等。
-
加载:
-
类加载器根据类的全限定名获取字节码信息。
-
类加载器在加载完类后,Java虚拟机会将字节码中的信息保存到内存的方法区中。在方法区生成一个InstanceKlass对象,保存类的所有信息。
-
在堆中生成一份与方法区中数据类似的java.lang.Class对象,作用是在Java代码中去获取类的信息。
- 比如这段代码中,就会访问堆中的Class对象:
-
- 连接:
- 验证:验证内容是否满足《Java虚拟机规范》。
- 准备:给静态变量赋初值。final变量直接赋值。
- 解析:将常量池中的符号引用替换成指向内存的直接引用。
- 初始化:执行静态代码块中的代码,并为静态变量赋值。执行字节码文件中clinit部分的字节码指令。
- 使用
- 卸载:需要同时三个条件
- 此类的所有实例对象已被回收
- 加载该类的类加载器已经被回收。
- 该类对应的java.lang.Class对象没有在任何地方被引用。
验证中有:
- 文件格式,0xCAFEBABE开头,主次版本号(java8是45)
- 元信息验证,比如类必须有父类 object
- 符号引用验证,是否访问其它类的private
new一个对象的过程
- 检查是否类加载
- 分配内存空间
- 分配方式:根据堆中内存是否规整,有两种分配内存的方式。指针碰撞;空闲列表。
- 并发问题:两种解决方案。cas对分配内存的动作进行同步处理;TLAB本地线程分配缓冲,每个线程在java堆中预先分配一小块内存,优先从TLAB中分配。
- 初始化零值
- 设置对象头
- 执行init() 方法
什么是类加载器
- 启动类加载器(Bootstrap ClassLoader) 加载核心类。
- 扩展类加载器(Extension ClassLoader)加载扩展类。
- 应用程序类加载器(Application ClassLoader)加载classpath中的类。
- 自定义类加载器,重写findClass方法。