堆解决数据存储的问题,栈解决程序如何运行和数据如何处理的问题。
java堆是JVM内存中最大的一块,由所有线程共享,是由垃圾收集器管理的内存区域,主要存放对象实例
下图来自终于搞懂了Java8的内存结构,再也不纠结方法区和常量池了!
JAVA8 内存模型
JVM内存模型以及JDK7和JDK8内存模型对比总结
通过jmap分析内存泄漏
在linux下面才能执行的,windows中执行不了
# 什么类一直在增长,就是嫌疑犯了。windows只能写入到log中帅选了
jmap -histo 6220 > a.log
# 在linux环境下可以执行
[root@wd8 ~]# jmap -histo:live 2547|head -n 10
num #instances #bytes class name
----------------------------------------------
1: 13036 121602072 [B
2: 124376 18589896 [C
3: 22531 14658440 [Ljava.lang.Object;
4: 122682 2944368 java.lang.String
5: 8683 2380544 [I
6: 49152 2359296 com.alipay.sofa.jraft.core.FSMCallerImpl$ApplyTask
7: 68400 2188800 java.util.concurrent.ConcurrentHashMap$Node
# 查看对象数最多的对象,按降序输出
jmap -histo pid | sort -k 2 -g -r
# 查看内存的对象,按降序输出
jmap -histo pid | sort -k 3 -g -r
这里看一下nacos启动后,通过jmap -heap 8556
查看堆的使用情况,下面是nacos中的默认jvm配置情况
set "NACOS_JVM_OPTS=-Xms512m -Xmx512m -Xmn256m"
集群下的配置
set "NACOS_JVM_OPTS=-server -Xms2g -Xmx2g -Xmn1g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=%BASE_DIR%\logs\java_heapdump.hprof -XX:-UseLargePages"
下图做了windows和linux下面同一个nacos应用进程的堆使用情况
1 Parallel GC with 4 thread
JDK8的Parallel GC with 4 thread(s)的真正含义
2 NewRatio SurvivorRatio
JVM -XX:NewRatio、-XX:SurvivorRatio参数含义
JVM参数之SurvivorRatio和NewRatio
大家都知道Eden:survior from:survivor to的比例为8:1:1,SurvivorRatio中的8,表示就是这三个区域的比例
Eden+2*Survivor:Old的比值,即是NewRatio ,默认为2
可是为何上图中从capacity中看到单个进程比例完全不是这么回事。
JVM调优总结 -Xms -Xmx -Xmn -Xss
-Xms,就是上图的MaxHeapSize,最大可用内存
-Xmx,此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存
-Xmn,新生代(年轻代)的大小。
JDK1.8为什么废弃永久代【一篇就够】,jdk1.8以前还有个固定的64M的持久代,但现在被元数据空间替代了。由于永久代内存经常不够用或发生内存泄露,爆出异常java.lang.OutOfMemoryError: PermGen
从上图看到MaxMetaspaceSize = 17592186044415 MB
,因为元数据空间使用的是本地内存,故而理论上没有上限。而MetaspaceSize初始为20M
执行java -XX:+PrintFlagsInitial
查看初始化了哪些东西,打印出来,但是也看不懂.
但元数据空闲上限默认很大,但因为它会占本地内存,故而对服务器上的应用会有影响,需要关注