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即可

如tomcat配置
 
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%。应该是起到效果了。

 

 

 

 

posted @   逆风飞翔的博客  阅读(19)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示