深入浅出Java虚拟机-Java编译概述
Posted fesng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入浅出Java虚拟机-Java编译概述相关的知识,希望对你有一定的参考价值。
Java虚拟机存储
上图分为线程共享和非共享,其中堆内存是用来存放Java对象的,虚拟机栈和本地方法栈都是存放方法信息,前者是通过栈帧结构存放方法的参数和本地变量,以及方法的返回地址和调用地址等信息,后者是存放本地方法的信息。
方法区是存放类和常量的信息的。
如何判断内存垃圾
主要是对上面四种引用的可达性分析。
可达性分析解决了循环引用的问题。
分析的起点(GC ROOT)分为四类:
垃圾收集算法
垃圾回收的本质是可达性分析
1.标记清除
2…复制,量少的时候
3.标记,整理,用于量多,碎片化时候。
分代收集算法
新生代
分为新生代和老年代。新生代分为2个Survivor和一个Eden区域,默认比例为1:1:8,每次都是把一个Survivor和Eden剩下的对象复制到另一个Survivor。因为新生代死亡率高,所以采用复制算法,效率高,另外9:1的比例又能保证空间利用率高。
特殊情况:
1.什么时候进入老年代?
会给每个对象加一个时间阈值,到了就直接到老年代。对于那种较大的对象会直接进入老年代。
2.如果复制装不下怎么办?
担保机制失败,直接进入老年代。
老年代
老年代存放那种经过检验的短时间不会死亡的对象,所以这部分对象是通过标记-整理算法来做的。
编译过程
这部分是狭义的编译,指的是
1.第一阶段主要是词法和语法分析。
字节生成标记,标记就是包,变量等都是几个字节组成。
标记,主要是包括类,接口,变量,方法等,类似你在IDE看到的类结构,构成抽象语法数。
2.注解处理
这部分是我们能够参与的过程,能够直接影响抽象语法数的结构。
3. 语意分析和字节码生成
1.标注
这部分主要是检查,变量的是否生成,以及赋值类型是否对应。
2.数据和控制流分析
这部分是检查方法路径和异常等是否正常,和加载期间的验证的语意分析侧重点不一样,后者是字节码指令的角度。
3.解语法糖。
这部分的原意是Java的落后的语法在进行改进的时候,通过编译支持,而不是字节码指令的支持,不影响后面的JAVA的类的结构和字节码的支持,而是通过编译成旧版本的代码实现。
1.泛型
在编译器擦除,是假的泛型,List 和List是一样的。
2.装箱和拆箱
3.变长参数
4.if(true,false)条件编译
5.字节码生成
主要是实例构造函init和类构造clinit函数。
包括代码块,static,变量初始化,构造方法
顺序是:
构造器,方法快,初始化变量
JIT编译
整体是有限解释执行的,对应两类比较常用的代码,就是所谓的热点代码:
执行多次的方法和方法内部的循环体是会JIT做编译优化,整体的机制是通过一个计数的统计,达到一定的阈值会开始进入编译。
编译生成的class结构
字节码指令
类型
1.加载和存储指令
数值从操作数栈道局部变量表
load + 类型
将常量加载到操作数栈
push + 类型
2.运算指令
add sub mul div rem(求余) neg (取反)shl(位移)or and xor iinc(自增)
比较命令; dcmpg dcmpl fcmpg fcmpl
3.类型转化指令
宽化指令和窄化指令
4.对象创建和访问指令
new newArray get/put(filed/static) aload astore
5.操作数栈管理
pop dup swap(交换)
6.控制转移指令
if switch goto
7.方法调用和返回
8.异常指令
athrow
9.同步指令
管程 minor
monitorenter 和monitorexit来支持synchronized关键字。
Java虚拟机
Java虚拟机和Java语言是完全两个不同的概念,只要是能够编译成class文件的格式都能被Java虚拟机所编译,包括Groovy和Scala等。
虚拟机类的加载生命周期
1.加载阶段
这个阶段是我们能够最大化控制的。
什么时候加载一个类?
2.验证阶段
一.验证
1.文件格式验证
2.元数据验证
语法层面,类的继承,方法的重载,覆写等
3.字节码验证
对于字节码指令的验证
4.符号引用验证
二.准备
主要是把方法区的属性初始化为字面量的初始值,比如int 是0.
三.解析
3.初始化
类加载器
番外篇
对于虚拟机来说,不同的虚拟机加载的同一个class实际是不同的类。
双亲委派机制
虚拟机的字节码执行
参考:
本文参考自书籍《深入浅出Java虚拟机》
以上是关于深入浅出Java虚拟机-Java编译概述的主要内容,如果未能解决你的问题,请参考以下文章