一、JVM内存结构:
1.堆(线程共享):
存放静态变量、字符串常量池,分为新生代(伊甸园Eden+存活区(From survivor+To survivor))、老年代(Tenured)、元空间(本地内存Metaspace)。
2.虚拟机栈(线程隔离):
分为局部变量表、操作数栈(存放临时数据)、指向运行时常量池的引用、方法返回地址、动态链接。
3.本地方法栈(线程隔离):
使用C语言写的native方法
4.程序计数器(线程隔离):
为每个线程分配计数器,用来记录下一步执行的指令
5.方法区(线程共享):
存放静态变量(存堆中)、字符串常量池(存堆中)、类信息(版本/属性/方法/父接口或类/静态常量)(存元空间中)、运行时常量池(编译生成)(存元空间中)
二、类加载过程:
-> java原文件
-> 编译成class
-> 加载class:读取类、转换并存到方法区、在堆中产生Class对象
-> 链接:验证文件格式(class以0xCAFEBABE开头/版本号正确)/验证元数据(是否继承父类/是否非法继承final类/非abstract类是否实现所有abstract方法)/验证字节码(运行检查/栈数据类型+操作码操作参数无误/跳转指令指向正确位置)/验证符号引用(常量池中类是否存在/访问的属性及方法是否存在且有权限)、准备(为静态变量分配内存+初始化)、解析(符号引用转为直接引用)
-> 初始化:执行clinit方法(初始化静态变量/静态语句)、创建新对象执行init方法(初始化实例变量/执行构造块/执行构造方法)
-> 使用
-> 卸载
三、编译器:
1.执行模式(默认混合执行模式,一般使用解释执行,遇到频繁的代码时会转换成编译执行):
解释执行模式:将字节码转换一行执行一行。不用等待编译,总体性能差。
编译执行模式:将字节码转换为机器码,再执行机器码。性能好,但增加开销。
2.查看/设置执行模式:
C:\Users\Administrator>java -version #mixed mode表示混合执行模式
C:\Users\Administrator>java -Xint -version #设置为解释执行模式
C:\Users\Administrator>java -Xcomp -version #设置为编译执行模式,不能编译时会自动用解释执行模式
C:\Users\Administrator>java -Xmixed -version #设置为混合执行模式
3.Hostspot编译器分类:
C1即时编译器:适用客户端局部快速编译
C2即时编译器:适用服务端长期运行的Web程序
4.分层编译级别(别级越高,启动越慢,性能越高/开销越大):
说明:
0层:解释编译
1层(简单C1):简单优化编译代码(不开Profiling)
2层(受限C1):编译带方法调用次数及循环回边执行次数Profiling的部分代码
3层(完全C1):编译带有所有Profiling的代码
4层(C2编译):启用耗时的优化编译,会根据性能监测信息进行优化
只启用0层、4层编译,禁用1、2、3层:
-XX:-TieredCompilation
只启到到第n层编译,禁用后面层:
-XX:+TieredCompilation -XX:TieredStopAtLevel=n #n可设值为0、1、2、3、4
5.Hostspot计数器分类(可识别热点方法):
(1)方法调用计数器:
说明:
统计方法调用次数,未开分层编译时C1编译器默认1.5千次/C2编译器默认1万次(修改次数:
-XX:CompileThreshold=n),开启分层编译时动态调整阀值
流程:
方法入口 -> 未编译时方法调用计数器值+1(默认使用相对次数)/已编译时执行机器码并结束流程 -> 2个计数器值超过阀值/未超阀值时以解释方式执行代码并结束流程 -> 提交编译请求 -> 解释方式执行代码并结束流程
VM options中半闭计数器热度衰减(使用绝对次数):
-XX:-UseCounterDecay
VM options中设置计数器半衰周期(单位为秒):
-XX:CounterHalfLifeTime
(2)回边计数器(触发OnStackReplacement编译):
说明:
统计方法