导图社区 JVM 的学习总结
关于 JVM 的学习笔记,包括类加载机制,GC算法,垃圾回收器,内存空间及相关调优命令介绍
编辑于2020-04-07 15:13:19JVM
GC
存活对象判断
引用计数
每个对象都有一个引用计数属性,新增一个引用时+1,释放时-1,当计数为0时可回收 <无法解决循环引用的问题>
可达性分析
从 GC Roots 开始,开始往下搜索,当一个对象到 GC Roots 没有任何引用时即可回收
垃圾收集算法
标记-清除算法
不存活的对象标记起来直接清除
缺点:效率低下,内存空间不连续了
复制算法
将内存空间均分为二,存活的对象复制到一端,直接清理另一端即可
缺点:可用空间缩小一半,复制大量对象导致效率低下
标记-整理算法
存活对象压缩了一端,清理掉另一端即可
分代收集算法
年轻代用标记-清除算法,老年代用标记-压缩算法
垃圾收集器
Serial 收集器
使用算法:新生代复制算法、老年代标记-压缩
参数设置:<-XX:+UseSerialGC>
ParNew 收集器
使用算法:新生代复制算法、老年代标记-压缩
参数设置:<-XX:+UseParNewGC -XX:ParallelGCThreads>
Parallel 收集器
使用算法:新生代复制算法、老年代标记-压缩
参数设置:<-XX:+UseParallelGC>
Parallel Old 收集器
使用算法:多线程和“标记-整理”算法
参数设置:<-XX:+UseParallelOldGC>
CMS(Concurrent Mark Sweep)收集器
使用算法:标记-清除算法,并发收集、低停顿
参数设置:<-XX:+UseConcMarkSweepGC 使用CMS收集器-XX:+ UseCMSCompactAtFullCollection Full GC后,进行一次碎片整理;整理过程是独占的,会引起停顿时间变长-XX:+CMSFullGCsBeforeCompaction 设置进行几次Full GC后,进行一次碎片整理-XX:ParallelCMSThreads 设定CMS的线程数量(一般情况约等于可用CPU数量>
G1 收集器
GC 日志收集
配置参数
-XX:+PrintGC 输出GC日志-XX:+PrintGCDetails 输出GC的详细日志-XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)-XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式)-XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息-Xloggc:../logs/gc.log 日志文件的输出路径
调优命令
jps <jps [options] [hostid]>
参数
-l : 输出主类全名或jar路径-q : 只输出LVMID-m : 输出JVM启动时传递给main()的参数-v : 输出JVM启动时显示指定的JVM参数
常用命令
jps -l 2832jps -v 2832
jstat <jstat [option] LVMID [interval] [count]>
参数
-class class loader的行为统计-compiler HotSpt JIT编译器行为统计-gc 垃圾回收堆的行为统计-gccapacity 各个垃圾回收代容量(young,old,perm)和他们相应的空间统计-gcutil 垃圾回收统计概述-gccause 垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因-gcnew 新生代行为统计-gcnewcapacity 新生代与其相应的内存空间的统计-gcold 年老代和永生代行为统计-gcoldcapacity 年老代行为统计-gcpermcapacity 永生代行为统计-printcompilation HotSpot编译方法统计
常用命令
jstat -gc 2832 1000 10 每个1秒统计一下2832的gc情况,总共打印10次
jmap <jmap [option] LVMID>
参数
-dump : 生成堆转储快照-finalizerinfo : 显示在F-Queue队列等待Finalizer线程执行finalizer方法的对象-heap : 显示Java堆详细信息-histo : 显示堆中对象的统计信息-permstat : to print permanent generation statistics-F : 当-dump没有响应时,强制生成dump快照
常用命令
jmap -heap 2832 查看进程2832的堆情况
jhat <jhat [dumpfile]> 经常与命令 jmap 连用
jstack <jstack [option] LVMID>
参数
-F : 当正常输出请求不被响应时,强制输出线程堆栈-l : 除堆栈外,显示关于锁的附加信息-m : 如果调用到本地方法的话,可以显示C/C++的堆栈
常用命令
jstack -l 2832 | more
jinfo <jinfo [option] [args] LVMID>
参数
-flag : 输出指定args参数的值-flags : 不需要args参数,输出所有JVM参数的值-sysprops : 输出系统属性,等同于System.getProperties()
常用命令
jinfo -flags 2832
内存空间
heap 堆 <存放创建对象的实例,线程共享>
老年代
年轻代
又分为 Eden 区,From Survivor 区,To Survivor区8:1:1
命令参数
-Xms设置堆的最小空间大小。-Xmx设置堆的最大空间大小。-XX:NewSize设置新生代最小空间大小。-XX:MaxNewSize设置新生代最大空间大小
方法区 <存储类信息、常量、静态变量等数据,线程共享>
也被称作永久代,java8中去掉了方法区,叫做MetaSpace也被称为 非堆区
命令参数
-XX:PermSize设置永久代最小空间大小。-XX:MaxPermSize设置永久代最大空间大小
栈 <为方法执行服务,线程私有>
本地方法栈
JVM 栈
命令参数
-Xss设置每个线程的堆栈大小
类加载
什么是类的加载?
类的加载是指读取.class文件的二进制数据到内存中,将其放到运行时数据区的方法区内,并在堆区创建java.lang.class对象,该对象用于封装类在方法区的数据结构,用于提供相应的接口和方法。类加载器会预料某个类即将被加载,然后预先加载它,如果加载过程中出现错误并不会立即抛出,而是等到该类被第一次调用的时候才报告错误。
类的生命周期
1、加载 <.class加载到内存方法区,堆区生成对象>2、验证 <确保被加载的类的正确性>3、准备 <为类的静态变量分配内存,并将其初始化为默认值>4、解析 <把类中的符号引用转换为直接引用>5、初始化 <为类的静态变量赋予正确的初始值>
类加载器
1、启动类加载器 <Bootstrap ClassLoader>2、扩展类加载器 <Extension ClassLoader>3、应用程序加载器 <Application ClassLoader>
类的加载方式
1、命令行启动应用时候由JVM初始化加载2、通过Class.forName()方法动态加载3、通过ClassLoader.loadClass()方法动态加载
双亲委派模型
如果应用程序启动类收到了类加载的请求,会将请求传递给扩展类加载器加载,扩展类加载器会将请求传递给启动类加载器。启动类加载器如果找不到类,则让扩展类加载器加载,如果扩展类加载器也找不到,就让应用程序加载器加载