1.查看java进程,jps命令可以列出正在运行的虚拟机进程
1 2 3 4
| jps -l 1005373 sun.tools.jps.Jps 1000153 org.apache.flume.node.Application
|
2.查看flume进程java虚拟机的统计信息
1 2 3 4
| jstat -gcutil 1028479 S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 71.69 0.00 25.63 0.14 96.56 89.78 116 1.074 0 0.000 1.074
|
某springboot web服务进程java虚拟机的统计信息
1 2 3 4
| jstat -gcutil 29 S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 76.84 0.00 47.11 55.27 96.06 93.04 28 17.787 4 8.589 26.376
|
对应指标的中文含义
S0:Survivor0的占用比例
S1:Survivor1的占用比例
E:新生代Eden区的占用比例
O:老年代的占用比例
M:方法区的占用比例
CCS:压缩类空间的占用比例
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
3.查看jvm使用的是什么垃圾收集器
1 2 3 4 5 6
| java -XX:+PrintCommandLineFlags -version -XX:InitialHeapSize=2147483648 -XX:MaxHeapSize=32210157568 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC java version "1.8.0_121" Java(TM) SE Runtime Environment (build 1.8.0_121-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
|
使用的是并行垃圾收集器
JVM内存空间组成
Github:JVM 内存结构
Java 虚拟机的内存空间分为 5 个部分:
1 2 3 4 5 6
| 程序计数器 Java 虚拟机栈 本地方法栈 堆 方法区
|
图来自:【JVM学习】——本地方法栈、堆
配置参数
参考:JVM内存调优总结 -Xms -Xmx -Xmn -Xss 参数设置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 堆设置 -Xms :初始堆大小 -Xmx :最大堆大小 -XX:NewSize=n :设置年轻代大小 -XX:NewRatio=n: 设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4 -XX:SurvivorRatio=n :年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5 -XX:MaxPermSize=n :设置持久代大小 收集器设置 -XX:+UseSerialGC :设置串行收集器 -XX:+UseParallelGC :设置并行收集器 -XX:+UseParalledlOldGC :设置并行年老代收集器 -XX:+UseConcMarkSweepGC :设置并发收集器 垃圾回收统计信息 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:filename 并行收集器设置 -XX:ParallelGCThreads=n :设置并行收集器收集时使用的CPU数。并行收集线程数。 -XX:MaxGCPauseMillis=n :设置并行收集最大暂停时间 -XX:GCTimeRatio=n :设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n) 并发收集器设置 -XX:+CMSIncrementalMode :设置为增量模式。适用于单CPU情况。 -XX:ParallelGCThreads=n :设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。
|
1.程序计数器
程序计数器(Program Counter Register),在JVM规范中,每个线程都有自己的程序计数器。这是一块比较小的内存空间,存储当前线程正在执行的Java方法的JVM指令地址,即字节码的行号。如果正在执行Native方法,则这个计数器为空。该内存区域是唯一一个在Java虚拟机规范中没有规定任何OOM情况的内存区域。
2.Java虚拟机栈
Java虚拟机栈(Java Virtal Machine Stack),同样也是属于线程私有区域,每个线程在创建的时候都会创建一个虚拟机栈,生命周期与线程一致,线程退出时,线程的虚拟机栈也回收。虚拟机栈内部保持一个个的栈帧,每次方法调用都会进行压栈,JVM对栈帧的操作只有出栈和压栈两种,方法调用结束时会进行出栈操作。
3.本地方法栈
本地方法栈(Native Method Stack)与虚拟机栈类似,本地方法栈是在调用本地方法时使用的栈,每个线程都有一个本地方法栈。
4.堆内存
使用jmap查看JVM的堆内存情况
堆(Heap),几乎所有创建的Java对象实例,都是被直接分配到堆上的。堆被所有的线程所共享,在堆上的区域,会被垃圾回收器做进一步划分,例如新生代、老年代的划分。Java虚拟机在启动的时候,可以使用“Xmx”之类的参数指定堆区域的大小。
堆内存分成 Young Generation(年轻代)和 Old Generation(老年代)
此外,Young Generation(年轻代)还分成 Eden Space , From Space 和 To Space(也叫 Survivor0空间 和 Survivor1空间)
JVM参数设置参考:JVM系列三:JVM参数设置、分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| jmap -heap 29 Attaching to process ID 29, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.121-b13
using thread-local object allocation. Parallel GC with 33 thread(s)
Heap Configuration: MinHeapFreeRatio = 0 MaxHeapFreeRatio = 100 MaxHeapSize = 32210157568 (30718.0MB) NewSize = 715653120 (682.5MB) MaxNewSize = 10736369664 (10239.0MB) OldSize = 1431830528 (1365.5MB) NewRatio = 2 SurvivorRatio = 8 MetaspaceSize = 21807104 (20.796875MB) CompressedClassSpaceSize = 1073741824 (1024.0MB) MaxMetaspaceSize = 17592186044415 MB G1HeapRegionSize = 0 (0.0MB)
Heap Usage: **PS Young Generation** Eden Space: capacity = 5859442688 (5588.0MB) used = 2972839024 (2835.1202239990234MB) free = 2886603664 (2752.8797760009766MB) 50.73586657120658% used From Space: capacity = 505937920 (482.5MB) used = 388770920 (370.7608413696289MB) free = 117167000 (111.7391586303711MB) 76.84162515432723% used To Space: capacity = 558891008 (533.0MB) used = 0 (0.0MB) free = 558891008 (533.0MB) 0.0% used **PS Old Generation** capacity = 2802843648 (2673.0MB) used = 1549069632 (1477.3079223632812MB) free = 1253774016 (1195.6920776367188MB) 55.26778609664352% used
|
5.方法区
方法区(Method Area)。方法区与堆一样,也是所有的线程所共享,存储被虚拟机加载的元(Meta)数据,包括类信息、常量、静态变量、即时编译器编译后的代码等数据。这里需要注意的是运行时常量池也在方法区中。根据Java虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。由于早期HotSpot JVM的实现,将CG分代收集拓展到了方法区,因此很多人会将方法区称为永久代。Oracle JDK8中已永久代移除永久代,同时增加了元数据区(Metaspace)。
6.运行时常量池
运行时常量池(Run-Time Constant Pool),这是方法区的一部分,受到方法区内存的限制,当常量池无法再申请到内存时,会抛出OutOfMemoryError异常。
7.直接内存
直接内存(Direct Memory),直接内存并不属于Java规范规定的属于Java虚拟机运行时数据区的一部分。Java的NIO可以使用Native方法直接在java堆外分配内存,使用DirectByteBuffer对象作为这个堆外内存的引用。