JVM
学习目的
- 有效防止内存泄漏
- 优化线程锁的使用
- 科学地进行内存回收
- 提高系统吞吐量
- 降低延时,提高性能
字节码底层执行顺序
在主流的JVM(如HotSpot)中实现了两种执行方式
- 热点代码 : 一般泛指循坏或者高频使用的方法
- 解释执行器 : 负责将字节码翻译成机械码并执行
- 编译执行器 : 负责即时编译(just-in-time compilation , JIT)
JIT :
用以提高代码效率,基于这种技术,字节码编译成平台相关的原生机器码,并进行各个层次的优化。这些机器码会被缓存起来,以便下次快速使用(会增加内存负担)
JVM的运行模式
cmd中 java -version 查看
Server模式(64bit 默认)
- 启动速度慢,进入稳定期后速度相比较更快
- 重量级虚拟机(对锁\内存等使用方面进行优化)
Client模式
- 启动速度快,稳定后速度相对速度慢
- 轻量级虚拟机
JVM架构
主要有三大部分
- 类加载区:加载类到内存
- 运行时数据区:负责存储数据信息
- 执行引擎:负责调用对象执行业务(jit、gc、解释器)
运行内存架构
堆区域
GC的主要管理区域
年轻代首先进入
优先放置其中的伊甸园区,待区域满了,GC启动,转入幸存区的From区
From和To区中相互转化,且永远有一个空的
再一次GC(伊甸园和From皆有回收),From中没有被回收的资源转入To,
To转换为From,且资源年龄+1
年龄大的资源被GC回收,进入老年代
老年代进入方式
- 年轻代GC至老年代
- 年轻代空间满即伊甸园空间不足,创建对象时直接出生再老年代(部分小对象也有可能进入虚拟机栈)
方法区(元空间、持久代)
在JDK8中是一块本地内存(脱离了JVM),由OS动态配置,可以手动设置最大空间
程序计数器
- 线程启动时创建,线程私有
- 记录当前正在执行的虚拟机字节码指令地址
- 该区域不会存在内存溢出
栈
- 存储栈帧对象
- 方法的一次调用就会经历一次压栈和出栈
- 小对象(十几个bytes)且没有逃逸(没有全局声明)会创建在此
- 容易在递归时(未使用尾递归优化)发生栈内存溢出
本地方法栈
调用本地的方法,java调用非java代码的接口
执行引擎
- interpreter(解释器):即时运行,变编译边执行代码
- JIT :缓存热点代码,下次调用免编译直接运行
- 垃圾收集器:收集垃圾对象
调优概述
堆主要着手以下方面
-XMS 堆空间的最小大小
-XMX 堆空间的最大大小
-XX: NewSize 新生代最小空间
-XX: MAXNewSize 新生代最大空间
-XX: NewRatio 老年代和新生代的比值
-XX: SurvivorRatio eden 和 单个Survivor的比值 例如8 等于 eden :Survivor = 8 :2
-Xss 每个线程大小
方法区(JDK8)
- -XX:MetaspaceSize 最小空间
- -XX:MaxMetaspaceSize 最大空间
栈
- -Xss 越小可以创建的线程越多,注意OS对单个进程可以创建的线程数最多在3000-5000之间
常用监控工具
1、jps 进程监控工具
查看虚拟机正在运行的进程信息,可追踪到应用进程ID 、启动类名、文件路径。
2、jstat性能监控工具
用于监视内存各个区域的使用情况、垃圾回收情况
3、jinfo 参数配置监控工具
查询和调整JVM 配置信息。
4、jmap内存监控工具
生存堆内存快照文件,查询堆内存配置和使用状况。
5、jstatck线程监控工具
生成虚拟机当前时刻的线程快照文件。
6、可视化工具VisualVM(类似的很多)
jdk自带,可以进行本地和远程监控