jvm问题分析
java堆内存情况
1.查看当前内存大小
jmap -heap pid pid为 可以通过 ps -ef|grep java(或者关键字来查询) [root@htcf-sc-27 script]# jmap -heap 7726 Attaching to process ID 7726, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.131-b11 using thread-local object allocation. Parallel GC with 8 thread(s) Heap Configuration: MinHeapFreeRatio = 0 MaxHeapFreeRatio = 100 MaxHeapSize = 2147483648 (2048.0MB) NewSize = 536870912 (512.0MB) MaxNewSize = 536870912 (512.0MB) OldSize = 1610612736 (1536.0MB) 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 = 509607936 (486.0MB) used = 113671704 (108.4057846069336MB) free = 395936232 (377.5942153930664MB) 22.30571699731144% used From Space: capacity = 13631488 (13.0MB) used = 11747344 (11.203140258789062MB) free = 1884144 (1.7968597412109375MB) 86.17800199068509% used To Space: capacity = 13631488 (13.0MB) used = 0 (0.0MB) free = 13631488 (13.0MB) 0.0% used PS Old Generation capacity = 1610612736 (1536.0MB) used = 104004576 (99.18649291992188MB) free = 1506608160 (1436.8135070800781MB) 6.457453966140747% used
整体内存可以分为堆区和非堆区
堆区:
所有new的对象都在堆区新生代、中生代、老年代源自于对堆区的细分java中每新new一个对象所占用的内存空间就是新生代的空间,当java垃圾回收机制对堆区进行资源回收后,那些新生代中没有被回收的资源将被转移到中生代,中生代的被转移到老生代。-XX:MaxNewSize=518等是对新生代的最大值进行设置。
非堆区:
包括持久带,用来存放静态文件,如java类,方法等。
下面参数:
1.堆(Heap)内存分配 -Xms : 初始堆大小 -Xmx: 最大堆大小,可设置为与Xms一样 -XX:NewSize=n:设置年轻代大小 2.堆(Heap)内存分配 -XpermSize = n -XMaxPermSize = n 注意-XMaxPermSize和-Xmx的总和不能超过物理机的最大内存值
查询结果如下
Heap Configuration:(MaxHeapSize) = 1004535808 (958.0MB) //最大堆大小,默认为物理内存的1\ 4NewSize = 1310720 (1.25MB)MaxNewSize = 17592186044415 MB //64位操作系统理论无限制 OldSize = 5439488 (5.1875MB)NewRatio = 2SurvivorRatio = 8PermSize = 21757952 (20.75MB) //非堆区大小
观察的几个参数:
MaxHeapSize,堆内存空间,也是我们最需要关注的,如果JVM没有设置,默认为服务器的1/4,所以看这个参数,就可以大概识别服务器JVM配置是否合理。当堆内存的年轻代进行YGC后,会有一部分对象进入老年代,当老年代满了会进行一个FGC,来再一次回收,如果FGC后依然没有办法回收大量对象,即有内存泄漏OOM。
2.设置当前内存大小
如果堆内存过小,我们怎么设置呢,调节xms和xms即可
JAVA_OPTS="-server -Xms10240M -Xmx10240M -Xss256k -XX:PermSize=128m -XX:MaxPermSize=128m -Xmn512m-Xms: 初始heap大小,使用的最小内存,cpu性能高时,此值应该设置的大一些-Xms: java heap最大值,使用的最大内存-XX: PerSize:设定的最大内存的永久保存区域
PermSize设置非堆内存初始值,默认是物理内存的1/64
MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4
Xss128k:设置每个线程的堆栈大小
-Xmn2g:设置年轻代大小为2G。整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小
3.定位内存的使用情况(GC情况)
通过查询jvm的heap堆内存情况,并结合业务以及服务器参数初步判断内存是否需要调节。那如果我们内存调节后,还是会出现这种情况,怎么办。
这时我们需要查看内存的YGC和FGC的情况,以及CMS内存回收为例:
YGC: 年轻代内存回收
FGC:老年代内存回收
如果对内存年轻代、老年代回收不太清楚,可以去科普下,但是也可以直接进入如果定位FGC情况。
查看当前jvm gc情况
jstat -gcutil pid 1000(1秒) 20(次)
S0:Survivor0已用内存百分比
S1:Survivor1已用内存百分比
E:eden已用内存百分比
O:老年代已用内存百分比
M:元空间已用内存百分比
CCS:压缩类空间已用内存百分比
YGC:Young GC触发次数
YGCT:耗时
FGC:Full GC次数
FGCT:耗时
GCT:总耗时
上图可以看到,当前JVM环境,O区老年代快照基本全是100%,也就是老年代已经满了,怎么都回收不掉。快照时间内,FGC已经从245次,增加到了246次,这么短的时间内,就进行来一次FGC,并且内存回收不掉,基本就是OOM了。
当JVM进行FGC的时候,服务的性能是非常低下的,因为JVM要去占用大量CPU去进行内存回收,业务侧看到的就是系统卡,变慢。服务器侧的表现就是CPU飙高。
4.定位了内存OOM,怎么定位到对象或者代码呢
4.1 jmap查看内存中的对象数目、大小统计直方图

如果能粗略定位到,异常的对象则可以直接定位到相关服务,或者代码。
但是现实往往没那么简单,jmap直方图基本很难看到异常。需要导出内存快照。
4.2导出内存快照dump用工具分析
root@ubuntu:/# jmap -dump:format=b,file=/tmp/dump.dat 21711 Dumping heap to /tmp/dump.dat ... Heap dump file created dump出来的文件可以用MAT、VisualVM等工具查看,这里用jhat查看:
关于内存泄漏的分析,可以把dump文件交给开发,或者运维和开发一起定位,本文不在展开,后续会有文章专门分析。
案例1优化:调节JVM堆内存,导出内存快照,定位是否有异常地方。
案例2分析:提示java.lang.OutOfMemoryError: PermGen space,故意思意,是非堆区的空间不够。
ps -ef|grep tomcat jmap -heap 19279 注意到perm Generation使用率已经84%,极有可能是非堆区空间不够用。上面配置也显示分配的默认PermSize为128M。
案例2优化:调节JVM非堆区。杀死服务,调整tomcat参数为
JAVA_OPTS="-server -Xms10240M -Xmx10240M -Xss256k -XX:PermSize=512m -XX:MaxPermSize=512m -Xmn1024m
继续查看堆内存使用情况,可以看到使用率变成17%。应该是起到效果了。

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!