JVM 内存模型
从内存申请方式划分
1. 栈 stack
方法区 method area
虚拟机栈 vm stack
本地方法栈 native stack
2. 堆 heap (内存申请方式)
堆 heap (这里的堆指的是存储对象的区域)
程序计数器 program counter register
3. 堆划分
1. 年轻代(young gem)
年轻代分为1个eden space 和2个survivor space
2. 老年代(old gem)
线程共享
线程共享: 方法区,堆
线程私有:虚拟机栈,本地方法栈,程序计数器
数据存储
1. 静态全局变量,方法:方法区(nethod)
2. 对象:堆(heap)
3. java局部变量:虚拟机栈.(vm stack)
4. 本地方法变量:本地方法栈(native stack)
5. 线程执行相关数据:程序计数器(program counter register)
参考:jvm 全面理解
jmap
jmap 必须安装open-jdk-debug ,执行时候需要用到root权限.
生产环境对jmap -dump ,histo:live ,permstat(1.8 clstats) 慎用,会触发应用暂停.
jmap -heap pid
查看对应pid的堆信息
jmap -dump:file=xxx.dump pid
dump对应pid堆信息
jmap -clstats
查看类加载信息
jvm 参数设定
-server//服务器模式
-Xms4g //JVM初始分配的堆内存,一般和Xmx配置成一样以避免每次gc后JVM重新分配内存。
-Xmx4g //JVM最大允许分配的堆内存,按需分配
-Xmn256m //年轻代内存大小,整个JVM内存=年轻代 + 年老代 + 持久代
-Xss512k //设置每个线程的堆栈大小
-XX:+DisableExplicitGC //忽略手动调用GC, System.gc()的调用就会变成一个空调用,完全不触发GC
-XX:+UseConcMarkSweepGC //并发标记清除(CMS)收集器
-XX:+CMSParallelRemarkEnabled //降低标记停顿
-XX:LargePageSizeInBytes=128m //内存页的大小
-XX:+UseFastAccessorMethods //原始类型的快速优化
-XX:+UseCMSInitiatingOccupancyOnly //使用手动定义初始化定义开始CMS收集
-XX:CMSInitiatingOccupancyFraction=70 //使用cms作为垃圾回收使用70%后开始CMS收集
-Duser.timezone=GMT+8 //设定GMT区域,避免CentOS坑爹的时区设置
-XX:MetaspaceSize //触发GC的元数据空间阈值,并非初始值.
-XX:InitialBootClassLoaderMetaspaceSize=256m //元数据初始值
-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代).设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5
-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值.设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6
这里看起来很多,其实并没有多少的.
首先,配置堆的最小值:-Xms4g,最大值:-Xmx4g;
然后配置年轻代:-Xmn256m 或配置比例:-XX:NewRatio=4;
再配置survivor区比例:-XX:SurvivorRatio=4;
最后可能需要配置每个线程堆大小:-Xss512k.
到这里,年轻代,内存配置完成.持久带(元数据) 一般不需要配置,默认20m ,最大没限制.其他都是一些配置垃圾收集器,这部分基本没什么修改的,一般eden区采用标记清除算法,survivor复制-清除算法之类的.copy就行.主要需要调整的就是eden ,survivor,调整这里,可以直接扩大年轻代.线程堆大小可能也需要调整.元数据区基本没什么好修改的.基本就是调大内存,调好年轻代大小,eden区大小.