JVM 内存

news/2024/9/19 12:36:25/文章来源:https://www.cnblogs.com/moonlight-lin/p/18417387

目录
  • 堆栈
  • 默认垃圾回收策略
  • 垃圾回收参数
  • G1 垃圾回收
  • 查看内存的命令


堆栈

堆:存储对象和数组,堆大小动态分配 (-Xms、-Xmx),线程共享,垃圾回收
栈:存储局部变量、方法参数、方法栈,相对较小 (-Xss),方法完成时释放,线程私有

堆栈大小配置

  • -Xmx:设置 JVM 最大可用内存,默认系统内存的 1/4,最大不超过 32GB
  • -Xms:设置 JVM 初始内存,默认系统内存的 1/64,最大不超过 1GB,建议与 -Xmx 相同,避免频繁的内存分配
  • -Xmn:设置年轻代大小,默认未指定
  • -Xss:设置线程的栈大小,通常默认为 1MB

如果大数据量、高并发,可以考虑把年轻代调大些,避免频繁触发 GC 使数据进入老年代,进而触发 fullGC

默认垃圾回收策略

Java 8: 默认 GC 策略是 Parallel GC,它通过并行处理垃圾收集来提高吞吐量,减少应用程序的暂停时间。

Java 11: 默认 GC 策略是 G1 GC(Garbage-First GC),G1 是为了处理大堆内存和满足低停顿时间的要求而设计的,它在 Java 9 及以后的版本中成为默认选择。

垃圾回收参数

  • 监控和调试:
    -verbose:gc、-XX:+PrintGCDetails、-XX:+PrintGCTimeStamps、-XX:+PrintGCDateStamps、-XX:+PrintGCCause

  • 生成 dump 文件:
    -XX:+HeapDumpOnOutOfMemoryError、-XX:HeapDumpPath

  • 指定收集器:
    -XX:+UseParNewGC:新生代使用并行收集器
    -XX:+UseParallelOldGC:老年代使用并行收集器
    -XX:+UseG1GC : 启用 G1 垃圾收集器(适用于大堆内存和需要较低停顿时间的应用)
    -XX:+UseParallelGC : 启用 Parallel 垃圾收集器(适用于需要高吞吐量的应用)
    -XX:+UseConcurrentMarkSweepGC : 启用 CMS 垃圾收集器(适用于需要低停顿时间的应用,但在 Java 11 中已被弃用,建议使用 G1)
    -XX:+UseZGC : 启用 ZGC(适用于超低延迟应用,Java 11 引入了 ZGC)
    -XX:+UseShenandoahGC : 启用 Shenandoah GC(Java 11 新特性,适用于低停顿时间应用)

G1 垃圾回收

目标:低延迟、高吞吐量、减少停顿

Region:与传统回收器不同,G1 将堆划分为多个 Region (1~32M),用于存放年轻代或老年代

年轻代包括 Eden、S0、S1

  • Eden:存放刚创建的对象
  • Survivor 0 (S0, From):GC 后存活的年龄大于 1 的对象
  • Survivor 1 (S1, To):GC 时将 S0 和 Edge 存活的对象年龄 +1 并搬到 S1,结束后和 S0 互换
  • Eden 区 和两个 Survivor 区的大小比例默认是 8:1:1,可以通过配置 -XX:SurvivorRatio=6 使比例变成 6:1:1

老年代

  • 对象年龄大于阈值 (XX:MaxTenuringThreshold,默认 15) 时会被挪到老年代
  • 年轻代和老年代的比例是 JVM 动态调整的,一般年轻代占堆内存的 1/3,老年代占堆内存的 2/3
  • -XX:NewRatio=3 可改变比例,使年轻代占 1/4,老年代占 3/4
  • -Xmn=1g 直接指定年轻代大小为 1g,剩余的给老年代

G1 GC 包括几个阶段

  • Minor GC
  • Mixed GC
  • Full GC

Minor GC/Young GC

  • 回收 Edge 和 S0 无效的对象,存活的对象则年龄 +1 后挪到 S1
  • 如果年龄大于阈值,或 S1 空间不够,就挪到老年代
  • 清空 Edge 和 S0
  • 互换 S0 和 S1
  • Minor GC 通常在 Edge 区满触发
  • Minor GC 是 STW (Stop-the-World) 事件,回收时所有线程暂停,但由于年轻代较小,且多数对象短时间内就会变得不可达,所以停顿较短

全局并发标记 (Concurrent Marking)

  • 堆使用率达到一定比例时 (默认45%) 触发,用来标记整个堆中的活跃对象
  • 与应用线程并发执行,不会引起明显停顿,会标记出哪些 Region 包含最多垃圾,以便后续回收

Mixed GC

  • G1 的一个重要特性,它不仅回收年轻代,还回收部分老年代 Region
  • Mixed GC 在并发标记阶段之后执行
  • 会优先回收垃圾最多的老年代 Region
  • Mixed GC 是部分 STW 操作,通过控制回收区域数量,可以将停顿时间控制在可接受的范围内

Full GC/Old GC

  • Full GC 通常在老年代空间不足时触发,或是 Mixed GC 无法有效回收老年代空间时触发
  • Full GC 是对整个堆内存(包括年轻代和老年代)的垃圾回收,通常伴随着较长的 STW 停顿

G1 参数

  • -XX:MaxGCPauseMillis=:垃圾回收的最大停顿时间目标 (不保证达到),默认值 200 毫秒
  • -XX:ConcGCThreads=:设置用于并发标记阶段的线程数,通常根据 CPU 数量自动调整
  • -XX:G1HeapRegionSize=:设置 G1 中每个 Region 的大小,默认为 1MB 到 32MB
  • -XX:InitiatingHeapOccupancyPercent=:启动并发标记的条件,默认值 45%
  • -XX:G1MixedGCCountTarget:一次并发标记周期后,最多执行多少次 Mixed GC(默认为 8 )
  • -XX:G1MixedGCLiveThresholdPercent=:设置允许参与混合回收的老年代 Region 的存活对象的最大百分比。默认值是 85%,即存活对象超过 85% 的 Region 不会参与混合回收

G1 的优势

  • 可预测的停顿时间:通过 MaxGCPauseMillis 可以控制 GC 停顿时间,适合对延迟敏感的应用
  • 更高的吞吐量:G1 在大内存环境下表现优越,特别是使用多核 CPU 时
  • 灵活的内存管理:动态分配 Eden、Survivor 和 Old Region,并根据垃圾多少优先回收,提升内存使用效率

适用场景

  • 大内存应用:如内存超过 6GB,甚至几十 GB 的场景
  • 对停顿时间敏感的应用:例如金融交易系统、电商网站和在线服务等要求低延迟的应用

查看内存的命令

不同命令计算出来的堆内存的容量和已用量,是一样的

堆内存的容量,一开始与 -Xms 相关,最大值受 -Xmx

堆内存实际使用量可能远小于容量,会造成从系统层面看 JVM 的内存使用很稳定,但内部实际用量可能在不断增加的可能


jps -v:查看 java 程序的 pid 和命令

$ jps -v
13070 QuorumPeerMain -Dzookeeper.log.dir=/home/lin/Desktop/Software/apache-zookeeper-3.9.2-bin/bin/../logs -Dzookeeper.log.file=zookeeper-lin-server-lin-VirtualBox.log 
-XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError=kill -9 %p -Xmx1000m -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false

jstat -gc :查看 S0、S1、Eden、老年代、元空间的统计数据

$ jstat -gc 13070 5000 3S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT    CGC    CGCT     GCT   0.0    0.0    0.0    0.0   10240.0    0.0     20480.0     6840.9   13184.0 12597.7 1664.0 1491.1      1    0.008   1      0.019   0      0.000    0.0270.0    0.0    0.0    0.0   10240.0    0.0     20480.0     6840.9   13184.0 12597.7 1664.0 1491.1      1    0.008   1      0.019   0      0.000    0.0270.0    0.0    0.0    0.0   10240.0    0.0     20480.0     6840.9   13184.0 12597.7 1664.0 1491.1      1    0.008   1      0.019   0      0.000    0.027

S0C: 年轻代的 Survivor 0 区内存容量
S1C: 年轻代的 Survivor 1 区内存容量
S0U: 年轻代的 Survivor 0 区已用内存
S1U: 年轻代的 Survivor 1 区已用内存
EC: 年轻代的 Eden 区内存容量
EU: 年轻代的 Eden 区已用内存
OC: 老年代内存容量
OU: 老年代已用内存
MC: 元空间内存容量
MU: 元空间已用内存

已用堆内存就是 EU + OU


jmap -histo:live :列出每个类的实例总量和总内存,以及所有类的总内存

$ jmap -histo:live 13070num     #instances         #bytes  class name (module)
-------------------------------------------------------1:         21223        1802680  [B (java.base@11.0.24)2:            89        1512040  [J (java.base@11.0.24)3:         19951         478824  java.lang.String (java.base@11.0.24)4:          3632         438864  java.lang.Class (java.base@11.0.24)5:          4955         336496  [Ljava.lang.Object; (java.base@11.0.24)6:           232         275960  [C (java.base@11.0.24)7:          7140         228480  java.util.concurrent.ConcurrentHashMap$Node (java.base@11.0.24)8:          5557         177824  java.util.HashMap$Node (java.base@11.0.24)
... ...
Total        104576        6994872

jmap --heap --pid :Java 7,列出 heap 的配置、S、Eden、Old 的容量和使用量
jhsdb jmap --heap --pid :Java 11

$ jhsdb jmap --heap --pid 13070
Attaching to process ID 13070, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 11.0.24+8-post-Ubuntu-1ubuntu320.04using thread-local object allocation.
Garbage-First (G1) GC with 8 thread(s)Heap Configuration:MinHeapFreeRatio         = 40MaxHeapFreeRatio         = 70MaxHeapSize              = 1048576000 (1000.0MB)NewSize                  = 1363144 (1.2999954223632812MB)MaxNewSize               = 629145600 (600.0MB)OldSize                  = 5452592 (5.1999969482421875MB)NewRatio                 = 2SurvivorRatio            = 8MetaspaceSize            = 21807104 (20.796875MB)CompressedClassSpaceSize = 1073741824 (1024.0MB)MaxMetaspaceSize         = 17592186044415 MBG1HeapRegionSize         = 1048576 (1.0MB)Heap Usage:
G1 Heap:regions  = 1000capacity = 1048576000 (1000.0MB)used     = 16979456 (16.19287109375MB)free     = 1031596544 (983.80712890625MB)1.619287109375% used
G1 Young Generation:
Eden Space:regions  = 10capacity = 79691776 (76.0MB)used     = 10485760 (10.0MB)free     = 69206016 (66.0MB)13.157894736842104% used
Survivor Space:regions  = 3capacity = 3145728 (3.0MB)used     = 3145728 (3.0MB)free     = 0 (0.0MB)100.0% used
G1 Old Generation:regions  = 5capacity = 51380224 (49.0MB)used     = 3347968 (3.19287109375MB)free     = 48032256 (45.80712890625MB)6.516063456632653% used

jcmd GC.heap_info :列出类空间、元空间、堆内存的容量和使用量

$ jcmd 13070 GC.heap_info
13070:garbage-first heap   total 30720K, used 6840K [0x00000000c1800000, 0x0000000100000000)region size 1024K, 1 young (1024K), 0 survivors (0K)Metaspace       used 12597K, capacity 13032K, committed 13184K, reserved 1060864Kclass space    used 1491K, capacity 1658K, committed 1664K, reserved 1048576K

visualvm :图形工具,可查看堆内存容量和使用量

sudo apt-get install visualvm
visualvm

jconsole :图形工具,可查看堆内存容量和使用量

jconsole

jstack :查看线程栈信息

$ jstack 18812
Full thread dump OpenJDK 64-Bit Server VM (11.0.24+8-post-Ubuntu-1ubuntu320.04 mixed mode, sharing):Threads class SMR info:
_java_thread_list=0x00007f29a4001f10, length=29, elements={
0x00007f29ec017800, 0x00007f29ec106000, 0x00007f29ec108000, 0x00007f29ec10e800,
0x00007f29ec110800, 0x00007f29ec112800, 0x00007f29ec115000, 0x00007f29ec117000,
0x00007f29ec135000, 0x00007f29ec42b800, 0x00007f29ec6a2000, 0x00007f29ec6a3800,
0x00007f29ec6a5800, 0x00007f29ec6a7000, 0x00007f29ec6a9000, 0x00007f29ec6aa800,
0x00007f29ec6ac800, 0x00007f29ec6ae000, 0x00007f29ec6c0800, 0x00007f29ec6f1000,
0x00007f29ec6ff000, 0x00007f29ec700800, 0x00007f29ec702800, 0x00007f29ec724000,
0x00007f29ec727800, 0x00007f29ec72e800, 0x00007f29ec730800, 0x00007f29ec73f000,
0x00007f29a4001000
}"main" #1 prio=5 os_prio=0 cpu=734.14ms elapsed=26.23s tid=0x00007f29ec017800 nid=0xd6c waiting on condition  [0x00007f29f1a22000]java.lang.Thread.State: WAITING (parking)at jdk.internal.misc.Unsafe.park(java.base@11.0.24/Native Method)- parking to wait for  <0x00000000c7b05468> (a java.util.concurrent.CountDownLatch$Sync)at java.util.concurrent.locks.LockSupport.park(java.base@11.0.24/LockSupport.java:194)at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(java.base@11.0.24/AbstractQueuedSynchronizer.java:885)at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(java.base@11.0.24/AbstractQueuedSynchronizer.java:1039)at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(java.base@11.0.24/AbstractQueuedSynchronizer.java:1345)at java.util.concurrent.CountDownLatch.await(java.base@11.0.24/CountDownLatch.java:232)at org.apache.zookeeper.server.ZooKeeperServerMain.runFromConfig(ZooKeeperServerMain.java:185)at org.apache.zookeeper.server.ZooKeeperServerMain.initializeAndRun(ZooKeeperServerMain.java:113)at org.apache.zookeeper.server.ZooKeeperServerMain.main(ZooKeeperServerMain.java:68)at org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(QuorumPeerMain.java:141)at org.apache.zookeeper.server.quorum.QuorumPeerMain.main(QuorumPeerMain.java:91)"Reference Handler" #2 daemon prio=10 os_prio=0 cpu=0.46ms elapsed=26.14s tid=0x00007f29ec106000 nid=0xd73 waiting on condition  [0x00007f29bf7fe000]java.lang.Thread.State: RUNNABLEat java.lang.ref.Reference.waitForReferencePendingList(java.base@11.0.24/Native Method)at java.lang.ref.Reference.processPendingReferences(java.base@11.0.24/Reference.java:241)at java.lang.ref.Reference$ReferenceHandler.run(java.base@11.0.24/Reference.java:213)... ...
... ..."ContainerManagerTask" #31 daemon prio=5 os_prio=0 cpu=0.46ms elapsed=25.05s tid=0x00007f29ec73f000 nid=0xd96 in Object.wait()  [0x00007f29bcc6e000]java.lang.Thread.State: TIMED_WAITING (on object monitor)at java.lang.Object.wait(java.base@11.0.24/Native Method)- waiting on <0x00000000c8a388e0> (a java.util.TaskQueue)at java.util.TimerThread.mainLoop(java.base@11.0.24/Timer.java:553)- waiting to re-lock in wait() <0x00000000c8a388e0> (a java.util.TaskQueue)at java.util.TimerThread.run(java.base@11.0.24/Timer.java:506)"Attach Listener" #32 daemon prio=9 os_prio=0 cpu=1.62ms elapsed=13.45s tid=0x00007f29a4001000 nid=0xdbd waiting on condition  [0x0000000000000000]java.lang.Thread.State: RUNNABLE"VM Thread" os_prio=0 cpu=17.20ms elapsed=26.15s tid=0x00007f29ec103000 nid=0xd72 runnable  "GC Thread#0" os_prio=0 cpu=10.21ms elapsed=26.22s tid=0x00007f29ec02f800 nid=0xd6d runnable  "GC Thread#1" os_prio=0 cpu=7.23ms elapsed=25.21s tid=0x00007f29b4001000 nid=0xd82 runnable  "GC Thread#2" os_prio=0 cpu=11.72ms elapsed=25.21s tid=0x00007f29b4002800 nid=0xd83 runnable  "G1 Main Marker" os_prio=0 cpu=4.10ms elapsed=26.21s tid=0x00007f29ec04b800 nid=0xd6e runnable  "G1 Conc#0" os_prio=0 cpu=0.24ms elapsed=26.21s tid=0x00007f29ec04d800 nid=0xd6f runnable  "G1 Refine#0" os_prio=0 cpu=8.08ms elapsed=26.21s tid=0x00007f29ec0d4800 nid=0xd70 runnable  "G1 Refine#1" os_prio=0 cpu=1.11ms elapsed=25.20s tid=0x00007f29c4001000 nid=0xd84 runnable  "G1 Young RemSet Sampling" os_prio=0 cpu=16.52ms elapsed=26.21s tid=0x00007f29ec0d6000 nid=0xd71 runnable  
"VM Periodic Task Thread" os_prio=0 cpu=68.21ms elapsed=25.62s tid=0x00007f29ec431800 nid=0xd7d waiting on condition  JNI global refs: 18, weak refs: 0

显示不同线程的状态和栈信息



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/798714.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows的树形目录结构

一、文件、文件夹(目录)、逻辑盘、路径的概念文件:是操作系统用来存储和管理信息的基本单位文件夹也叫目录:是文件的集合体,文件夹中可包含多个文件,也可包含多个子文件夹。每个文件夹都有一个唯一的名称,用于在文件系统中标识和访问。逻辑盘,计算机的外存储器一…

高等数学 2.5 函数的微分

目录一、微分的定义二、微分的几何意义三、微分运算1、函数和、差、积、商的微分法则2、复合函数的微分法则四、微分在近似计算中的应用 一、微分的定义定义 设函数 \(y = f(x)\) 在某区间内有定义,\(x_0\) 及 \(x_0 + \Delta x\) 在这区间内,如果函数的增量 \[\Delta y = f(…

信息学奥赛初赛天天练-91-CSP-S2023基础题3-编译命令、树的重心、拓扑排序、进制转换、R进制转十进制、十进制转R进制

PDF文档公众号回复关键字:202409172023 CSP-S 选择题 1单项选择题(共15题,每题2分,共计30分:每题有且仅有一个正确选项) 11 以下哪个命令,能将一个名为 main.cpp 的 C++ 源文件,编译并生成一个名为 main 的可执行文件?( ) A g++ -o main main.cpp B g++ -o main.…

匀变速直线运动的规律

匀变速直线运动的规律 一、定义:匀变速直线运动为沿一条直线且加速度恒定不变的运动,在 \((v-t)\) 图中,其表示为一条倾斜的直线。二、关于字母的解释:\(v_0\) 表示初始速度,\(v_t\) 表示末速度,\(t\) 表示时间,\(a\) 表示加速度,\(s\) 代表位移。 三、关于匀变速直线运…

Java 性能调优:优化 GC 线程设置

垃圾回收器使用一组称为 GC 线程的线程来执行回收工作。有时 JVM 可能会分配过多或过少的 GC 线程。本文将讨论 JVM 为什么会出现这种情况、其影响以及可能的解决方案。 1 咋查找应用程序的 GC 线程数量 进行线程转储分析来确定应用程序的 GC 线程数量:从生产服务器捕获thread…

微信授权登录接口开发

微信登陆过程 在项目开发中,难免会遇到微信授权登录这一操作,本讲来讲一下微信登陆是如何实现的? 关于校验登录,有诸多方法,记录方法如下:使用Spring MVC提供的拦截器 网关服务全局过滤器 使用AOP面向横切面实现对于使用Spring MVC提供的拦截器来实现,其大致的思路如下:注…

1 计算机系统

计算机系统抽象层次6 用户 可执行程序5 高级语言 C++ Java4 汇编语言 汇编代码3 系统软件 操作系统 /库代码2 机器 指令集架构(ISA)1 控制(控制怎么执行) 微代码 /硬连线0 数字逻辑(执行) 电路、门等Language Processor: 语言处理器 语言处理器的两个阶段:分析源程序 合成目…

人工智能生成合成内容标识办法(征求 意见稿)发布

当前国家发布的关于人工智能生成合成内容标识的法律法规有:《中华人民共和国网络安全法》、《互联网信息服务算法推荐管理规定》、《互联网信息服务深度合成管理规定》、《生成式人工智能服务管理暂定办法》等。 征求意见稿 2024年9月14日,国家网信办发布关于《人工智能生成合…

南沙信奥老师解题:1167:再求f(x,n)

​ 用递归函数求解。【输入】第一数是x的值,第二个数是n的值。【输出】函数值。【输入样例】 1 2 【输出样例】 0.40#include <iostream> #include <stdlib.h> using namespace std; double f(double x,double n) {if(n==1)return x/(1+x);elsereturn x/(n+f(x,n-…

概率分布深度解析:PMF、PDF和CDF的技术指南

本文将深入探讨概率分布,详细阐述概率质量函数(PMF)、概率密度函数(PDF)和累积分布函数(CDF)这些核心概念,并通过实际示例进行说明。 在深入探讨PMF、PDF和CDF之前,有必要先简要介绍两种常用的概率分布:正态分布和均匀分布。 正态分布: 也称为高斯分布或钟形曲线,正…

冒泡排序(重要!)

1.作用 比较数组中两个相邻的数,如果第一个数比第二个数大,则会交换位置。 每一次比较都会产出最大或是最小的数,下一轮则可以少一次排序,依次循环,直到结束 2.机制 冒泡排序分为两个循环,外层冒泡轮数(总的次数循环),而内层比较大小(两个数进行比较) 可以想象有三个…

Luogu P10812

题目描述 给定一根 \(1\) 到 \(N\) 的数轴。一开始有一个棋子在 \(N\)。每次棋子 \(x\) 可以跳到 \(x-1,x+1\) 或 \(x\) 的因子处(不能超出 \(1\) 到 \(N\))。 每个点只能到达一次。求棋子到达 \(1\) 的方案数。 思路 由于求倍数比因子简单,所以把问题变成从 \(1\) 到 \(N\)…