JVM知识点整理-内存模型、垃圾回收、命令

JVM

参数

  • 标准参数(-),所有的JVM实现都必须实现这些参数的功能,java -help
  • 非标准参数(-X),默认jvm实现这些参数的功能,java -X
  • 非Stable参数(-XX),此类参数各个jvm实现会有所不同,将来可能会随时取消

内存模型

是运行时的单位,而是存储的单位。
堆中存的是对象,栈中存的是基本数据类型堆中对象的引用

堆(Heap)

  • 新生代(Young)
    Eden:新对象,装满触发YGC,依然存活会转移到S区
    Survivor(S0+S1)

  • 老年代(Old)
    装满触发FGC,依然无法放下,抛出OOM

默认内存比例:新生代1/3(E:4/5, S:1/5);老年代2/3

栈(Stack)

先进后出的数据结构,每个方法从开始调用到执行完成的过程,就是栈帧从入栈到出栈的过程
栈帧包括:局部变量表、操作栈、动态连接、方法返回地址等(一个方法对应一块栈帧内存区域)

  • 程序计数器:JVM指令码执行到的行号
  • 本地方法栈(native):System.currentTimeMillis()

场景:逆序输出、汉诺塔、数制转换

元空间(Metaspace)

JDK8开始,本地内存分配
存储包括:类元信息、字段、静态属性、方法、常量等

JVM运行时内存

年轻代(Young Generation)

所有新生成的对象首先都是放在年轻代的,年轻代分三个区:一个 Eden 区,两个 Survivor 区(S0,S1)。当 Eden 区满时,还存活的对象将被复制到 Survivor 区。

年老代(Old Generation)

在年轻代中经历了 N 次垃圾回收后仍然存活的对象,就会被放到年老代中。

持久代(Permanent Generation)

用于存放静态文件,如今 Java 类、方法等。
-XX:MaxPermSize=16m:设置持久代大小为 16m。
注:JDK1.8之后已经没有持久代的概念了,改为元数据 MetaspaceSize | MaxMetaspaceSize

总结

-Xms2048m:设置 JVM 初始内存为 2048m。此值可以设置与-Xmx 相同,以避免每次垃圾回
收完成后 JVM 重新分配内存。默认物理内存的 1/64。
-Xmx2048m:设置 JVM 最大可用内存为 2048m。默认物理内存的 1/4。

-Xmn1g:设置年轻代大小为 1G。堆大小 = 年轻代大小 + 年老代大小 + 持久代大小。
-XX:NewRatio=4:设置年轻代(包括 Eden 和两个 Survivor 区)与年老代的比值(除去持久代)。设置为 4,则年轻代与年老代所占比值为 1:4,年轻代占整个堆栈的 1/5
-XX:SurvivorRatio=4:设置年轻代中 Eden 区与 Survivor 区的大小比值。

-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m :设置元空间大小,设置成一样
-Xss128k:设置每个线程的堆栈大小。

垃圾回收

Minor GC

从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC

当 JVM 无法为一个新的对象分配空间时会触发 Minor GC,比如当 Eden 区满了。所以分配率越高,越频繁执行 Minor GC

Major GC

Major GC 是清理老年代

Mixed GC

是在G1收集器中独有的,用于收集整个young gen以及部分old gen的GC

Full GC

清理整个堆空间—包括年轻代、老年代及永久代(元数据空间)

GC日志

[GC (Allocation Failure) [ParNew: 367523K->1293K(410432K), 0.0023988 secs] 522739K->156516K(1322496K), 0.0025301 secs] [Times: user=0.04 sys=0.00, real=0.01 secs]
Allocation Failure:表明本次引起GC的原因是因为在年轻代中没有足够的空间能够存储新的数据了
ParNew:表明本次GC发生在年轻代并且使用的是ParNew垃圾收集器
367523K->1293K(410432K):单位是KB,三个参数分别为:GC前该内存区域(这里是年轻代)使用容量,GC后该内存区域使用容量,该内存区域总容量。
522739K->156516K(1322496K):三个参数分别为:堆区垃圾回收前的大小,堆区垃圾回收后的大小,堆区总大小。
[Times: user=0.04 sys=0.00, real=0.01 secs]:分别表示用户态耗时,内核态耗时和总耗时

垃圾回收器

串行收集器、并行收集器、并发收集器

串行收集器Serial

Serial收集器会冻结所有应用程序线程(SWT),使用单个垃圾回收线程来进行垃圾回收工作,新生代、老年代使用串行回收;新生代复制算法、老年代标记-压缩
-XX:+UseSerialGC
默认情况下,JDK5.0,以前都是使用串行收集器

ParNew收集器是Serial收集器的多线程版本,新生代并行,老年代串行;新生代复制算法、老年代标记-压缩
-XX:+UseParNewGC

并行收集器Parallel

Parallel收集器更关注系统的吞吐量,新生代复制算法、老年代标记-压缩【jdk8默认】
-XX:+UseParallelGC:选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置
下,年轻代使用并发收集,而年老代仍旧使用串行收集。
-XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾
回收。此值最好配置与处理器数目相等。
-XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集。JDK6.0 支持对年老代并行
收集。
-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为 1/(1+n)

并发收集器CMS

是一种以获取最短回收停顿时间为目标的收集器,基于“标记-清除”算法实现
-XX:+UseConcMarkSweepGC:使用CMS收集器
-XX:ParallelCMSThreads:设定CMS的线程数量
-XX:+UseCMSCompactAtFullCollection:Full GC后,进行一次碎片整理;整理过程是独占的,会引起停顿时间变长
-XX:+CMSFullGCsBeforeCompaction:设置进行几次Full GC后,进行一次碎片整理
-XX:+CMSIncrementalMode:设置为增量模式。适用于单 CPU 情况。

G1收集器

特点:空间整合(采用标记整理算法,不会产生内存空间碎片)、可预测停顿【jdk9+默认】
-XX:+UseG1GC

垃圾回收统计信息

-XX:+PrintGC 打印GC日志
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps

-Xloggc:gc.log 输出到文件✅
-XX:-DisableExplicitGC 禁用System.gc()的显示调用

查看GC类型: java -XX:+PrintCommandLineFlags -version

命令

jps

JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程。

-l : 输出主类全名或jar路径
-q : 只输出LVMID
-m : 输出JVM启动时传递给main()的参数
-v : 输出JVM启动时显示指定的JVM参数

jstat

用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。

jstat [option] LVMID
[option] : 操作参数
LVMID : 本地虚拟机进程ID

示例:

jstat -class 12709 # 监视类装载、卸载数量、总空间以及耗费的时间
jstat -gc 12709 # 垃圾回收堆的行为统计
OptionDisplays
classclass loader的行为统计。
compilerHotSpt JIT编译器行为统计。
gc垃圾回收堆的行为统计。
gccapacity各个垃圾回收代容量(young,old,perm)和他们相应的空间统计。
gcutil垃圾回收统计概述。
gccause垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因。
gcnew新生代行为统计。
gcnewcapacity新生代与其相应的内存空间的统计。
gcold年老代和永生代行为统计。
gcoldcapacity年老代行为统计。
gcpermcapacity永生代行为统计。
printcompilationHotSpot编译方法统计。

gc列详解:见附件一

jmap

用于生成heap dump文件,如果不使用这个命令,还阔以使用-XX:+HeapDumpOnOutOfMemoryError参数来让虚拟机出现OOM的时候·自动生成dump文件。

jmap [option] LVMID

dump : 生成堆转储快照
finalizerinfo : 显示在F-Queue队列等待Finalizer线程执行finalizer方法的对象
heap : 显示Java堆详细信息
histo : 显示堆中对象的统计信息
permstat : to print permanent generation statistics
F : 当-dump没有响应时,强制生成dump快照

示例:

jmap -dump:live,format=b,file=dump.hprof 12709 # dump堆到文件,format指定输出格式,live指明是活着的对象,file指定文件名
jmap -heap 12709 # 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况,可以用此来判断内存目前的使用情况以及垃圾回收情况
jmap -histo:live 28920 | more # 打印堆的对象统计,包括对象数、内存大小等等

*内存不足或泄露导出堆栈:-XX:+HeapDumpOnOutOfMemoryError
*可以使用mat或headAnalyze打开

jhat

与jmap搭配使用,用来分析jmap生成的dump,jhat内置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看
jhat [dumpfile]

示例:
jhat -J-Xmx512m dump.hprof
*jdk11已废弃

jstack

生成java虚拟机当前时刻的线程快照。

jstack [option] LVMID

-F : 当正常输出请求不被响应时,强制输出线程堆栈
-l : 除堆栈外,显示关于锁的附加信息
-m : 如果调用到本地方法的话,可以显示C/C++的堆栈

示例:

jstack -l 12709 | more

jinfo

实时查看和调整虚拟机运行参数

-flag : 输出指定args参数的值
-flags : 不需要args参数,输出所有JVM参数的值
-sysprops : 输出系统属性,等同于System.getProperties()

示例:

jinfo -flags 12709

javap

查看一个java类反汇编、常量池、变量表、指令代码行号表等等信息
javap -c -l xxx.class

JDK10+新增

  • jshell
  • jhsdb hsdb|jmap --|jinfo --|jstack –
  • jcmd pid help

线程的状态

Java中线程的状态分为6种

  1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
  2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。 线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。
  3. 阻塞(BLOCKED):表示线程阻塞于锁。
  4. 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
  5. 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
  6. 终止(TERMINATED):表示该线程已经执行完毕。

JMX和DEBUG

DEBUG
启动命令添加: java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar xxx.jar
IDEA Run Configurations选择Remote -> 填写IP和端口,选择模块,点击启动按钮 -> 在需要的行打上断点。

JMX
启动命令添加: java -Dcom.sun.management.jmxremote.port=18888 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=192.168.40.200 -jar xxx.jar

案例

# 查看占用内存过高的进程
top
# 查看进程占用的具体资源
top -H -p10000 (10000是Java进程的PID)
# 线程堆栈信息
jstack 10001 > jstack.txt
# GC运行信息
jstat -gcutil 10000 2000 10
# 内存占用信息
jmap -histo 10000 | more

附件一

S0C:年轻代中第一个survivor(幸存区)的容量 (字节)
S1C:年轻代中第二个survivor(幸存区)的容量 (字节)
S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
EC:年轻代中Eden(伊甸园)的容量 (字节)
EU:年轻代中Eden(伊甸园)目前已使用空间 (字节)
OC:Old代的容量 (字节)
OU:Old代目前已使用空间 (字节)
PC:Perm(持久代)的容量 (字节)  [MC]
PU:Perm(持久代)目前已使用空间 (字节)  [MU]
YGC:从应用程序启动到采样时年轻代中gc次数
YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)
FGC:从应用程序启动到采样时old代(全gc)gc次数
FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT:从应用程序启动到采样时gc用的总时间(s)
NGCMN:年轻代(young)中初始化(最小)的大小 (字节)
NGCMX:年轻代(young)的最大容量 (字节)
NGC:年轻代(young)中当前的容量 (字节)
OGCMN:old代中初始化(最小)的大小 (字节)
OGCMX:old代的最大容量 (字节)
OGC:old代当前新生成的容量 (字节)
PGCMN:perm代中初始化(最小)的大小 (字节)
PGCMX:perm代的最大容量 (字节)
PGC:perm代当前新生成的容量 (字节)
S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比
S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比
E:年轻代中Eden(伊甸园)已使用的占当前容量百分比
O:old代已使用的占当前容量百分比
P:perm代已使用的占当前容量百分比
S0CMX:年轻代中第一个survivor(幸存区)的最大容量 (字节)
S1CMX :年轻代中第二个survivor(幸存区)的最大容量 (字节)
ECMX:年轻代中Eden(伊甸园)的最大容量 (字节)
DSS:当前需要survivor(幸存区)的容量 (字节)(Eden区已满)
TT: 持有次数限制
MTT : 最大持有次数限制
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值