分析工具
jprofiler
mat 2 : eclipse memory analyzer
JDK 内置工具
https://blog.csdn.net/fenglibing/article/details/6411940
java 计算内存大小的工具
https://www.jianshu.com/p/9d729c9c94c4
dump 出进程内存
https://blog.csdn.net/renfufei/article/details/41444559
/opt/taobao/java/bin/jmap -dump:file=/tmp/1.bin,format=b pid
如果报:Unable to open socket file: target process not responding or HotSpot VM not loaded
则在前面加:sudo -u USERID (即进程的用户名)
公有云上用的:
sudo -u admin /opt/taobao/java/bin/jmap -dump:format=b,file=/tmp/%s/%s.bin %s
mac 上:
jmap -dump:format=b,file=/Users/shicai.xsc/Downloads/bin/10.bin 44005
IDEA debug 时分析内存
https://www.jetbrains.com/help/idea/analyze-objects-in-the-jvm-heap.html
dump 出内存文件后,mat 打开发现内存占用比线上使用的少
https://stackoverflow.com/questions/32271731/why-is-my-java-heap-dump-size-much-smaller-than-used-memory
When dumping its heap, the JVM will first run a garbage collection cycle to free any unreachable objects.
因为:dump 时会先做一次内存回收。
jhat
用途:是用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言
生成tomcat.bin dump文件后,使用jhat查看
root@blue-pc:/home/blue/apache-tomcat-7.0.39/conf# jhat tomcat.bin
.....
Started HTTP server on port 7000
Server is ready.
有时你dump出来的堆很大,在启动时会报堆空间不足的错误,可以使用如下参数:
jhat -J-Xmx512m heap.bin
shallow heap 和 retained heap 区别
https://blog.csdn.net/a740169405/article/details/53610689
换句话说,Retained Size就是当前对象被GC后,从Heap上总共能释放掉的内存。 不过,释放的时候还要排除被GC Roots直接或间接引用的对象。他们暂时不会被被当做Garbage。
jstat -gc 和 gc.log 中关于 Full GC 的数目不一致
https://blog.csdn.net/caomiao2006/article/details/47780765
MAT
-
使用的 tips
这个讲得非常好
https://eclipsesource.com/blogs/2013/01/21/10-tips-for-using-the-eclipse-memory-analyzer/
https://www.jianshu.com/p/759e02c1feee
-
用少内存来分析很大的 heap 文件
https://www.techpaste.com/2015/07/how-to-analyse-large-heap-dumps/
主要是给 MAT 的 MemoryAnalyzer.ini (Applications/mat%202.app/Contents/Eclipse/ 内)加上下面配置
-Xms6144m
-Xmx8192m
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+CMSParallelRemarkEnabled
-XX:+CMSClassUnloadingEnabled
-XX:+UseCMSInitiatingOccupancyOnly
-
查询变量值
select * from com.alibaba.cobar.net.handler.FrontendAuthenticator
select * from com.alibaba.cobar.config.UserConfig where (toString(name)="MEEGIRLCLOUDADMIN_DAILY_APP")
或者在 Histogram 页面中查询
-
通过 dominator_tree 找到最耗内存的线程
-
通过 thread_overview 找到线程调用栈
找出其中哪一个步骤耗费资源最多,以及当时的栈数据
Full GC
Full GC (Ergonomics)
https://blog.csdn.net/wwd0501/article/details/91465679
Full GC (Ergonomics)
2021-06-12T14:02:45.526+0800: 700.948: [Full GC (Ergonomics) [PSYoungGen: 65536K->65535K(98304K)] [ParOldGen: 131050K->131050K(131072K)] 196586K->196586K(229376K), [Metaspace: 76621K->76621K(1118208K)], 0.2264659 secs] [Times: user=1.10 sys=0.00, real=0.23 secs]
- 老年代内存使用达到极限。当发生几次Full GC后,老年代空间的内存使用仍然达到其容量极限时,我们可以知道老年代空间已经成为应用的瓶颈了。这可能是由于老年代空间分配不足,或者应用发生了内存泄漏。
默认的,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ),即:新生代 ( Young ) = 1/3 的堆空间大小。老年代 ( Old ) = 2/3 的堆空间大小。其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为 from 和 to,以示区分。
Full GC (Metadata GC Threshold)
https://blog.csdn.net/liubenlong007/article/details/78143285
2021-06-12T14:05:35.361+0800: 21.414: [Full GC (Metadata GC Threshold) [PSYoungGen: 24091K->0K(786432K)] [ParOldGen: 48045K->58688K(1048576K)] 72137K->58688K(1835008K), [Metaspace: 57670K->57670K(1099776K)], 0.1733414 secs] [Times: user=0.90 sys=0.01, real=0.17 secs]
-XX:MetaspaceSize=128M
各种 jvm 参数
https://www.cnblogs.com/easonjim/p/7490114.html
- -XX:PermSize=64M:JVM初始分配的非堆内存
- -XX:MaxPermSize=128M:JVM最大允许分配的非堆内存,按需分配
VM内存管理的机制:
1、堆(Heap)和非堆(Non-heap)内存
按照官方的说法:“Java虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在Java虚拟机启动时创建的。”,“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。
可以看出JVM主要管理两种类型的内存:堆和非堆。简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的,所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中。
Metaspacesize MaxPermSize 区别
https://www.jianshu.com/p/b448c21d2e71
https://www.cnblogs.com/dennyzhangdd/p/6770188.html
JDK8+移除了Perm,引入了Metapsace,它们两者的区别是什么呢?Metasace上面已经总结了,无论-XX:MetaspaceSize
和-XX:MaxMetaspaceSize
两个参数如何设置,随着类加载越来越多不断扩容调整,直到MetaspaceSize(如果没有配置就是默认20.8m)触发FGC,上限是-XX:MaxMetaspaceSize
,默认是几乎无穷大。而Perm的话,我们通过配置-XX:PermSize
以及-XX:MaxPermSize
来控制这块内存的大小,jvm在启动的时候会根据-XX:PermSize
初始化分配一块连续的内存块,这样的话,如果-XX:PermSize
设置过大,就是一种赤果果的浪费。很明显,Metapsace比Perm好多了^^;
JDK7 Perm 验证如下--设置-XX:PermSize=64m -XX:MaxPermSize=64m
,那么PC初始化就是64m:
jdk8中:
1.字符串常量由永久代转移到堆中。
2.持久代已不存在,PermSize MaxPermSize参数已移除。(看图中最后两行)
1.MetaspaceSize
初始化的Metaspace大小,控制元空间发生GC的阈值。GC后,动态增加或降低MetaspaceSize。在默认情况下,这个值大小根据不同的平台在12M到20M浮动。使用Java -XX:+PrintFlagsInitial命令查看本机的初始化参数
2.MaxMetaspaceSize
限制Metaspace增长的上限,防止因为某些情况导致Metaspace无限的使用本地内存,影响到其他程序。在本机上该参数的默认值为4294967295B(大约4096MB)。