jvm运行时数据区域总结:
1.程序计数器:当前线程所执行的字节码的行号指示器(线程私有)
如果线程正在执行的是native方法,该计数器值为空。 该区域是唯一没有outOfMemoryError的区域。
2.java虚拟机栈:描述方法执行的内存模型(线程私有)
方法执行时创建栈帧(栈帧存储着局部变量表:包括方法的入参,方法的局部变量;操作栈;动态链接;方法出口:即方法的返回地址)
方法从调用到完成就是对应夫人一个栈帧在虚拟机栈中从入栈到出栈的过程。
-Xss参数可以调整该区域的内存大小
发生内存溢出时:
若是多线程引起,1:升级硬件。
2:通过减少堆,方法区等其他内存区域大小,间接获取更大的栈空间。
3.本地方法栈:为虚拟机使用到Native方法服务(HotSpot把本地方法栈和java虚拟机栈合二为一)
-Xoss参数可调整该区域大小
4.java堆:在虚拟机启动时创建(线程共享) -Xmx,-Xms设置最大 最小值
分为新生代 和老年代
新生代又分为Eden区,Form区,To区 默认是按8:1:1的比例分配 -Xmn可设置新生代大小
发生OOM时可以-XX:+HeapDumpOnOutOfMemoryError配置打印出堆转储快照进行分析
1.分析是否是内存泄露(通过工具查看对象到GCRoot的引用链,看为何没有被垃圾回收)
2.若不是内存泄漏:检查堆参数:-Xmx,检查代码看是否对象生命周期太长
5.方法区(非堆);存储被虚拟机加载的类信息,常量,静态变量,常量池,字段描述,方法描述,即时编译器编译后的代码(线程共享)
又被称为“永久代”,这仅由于HotSpot把GC分代收集扩展至方法区
较少出现垃圾收集的行为:主要针对常量池回收和类型卸载
-XX:PermSize 和-XX:MaxPermSize设置该区域的最小 最大值
6.运行时常量池:是方法区的一部分,存放编译期生成的各种字面量 和 符号引用 和翻译出来的直接引用,在类加载之后存放
在运行期间也能将新的常量放入池中,如:String的intern()方法
属于方法区:所以可以通过-XX:MaxPermSize间接限制容量大小
7.直接内存:不是虚拟机运行时数据区的一部分
NIO:基于通道和缓冲区的I/O方式,可以使用Native函数库分配堆外内存,java堆中有一个DirectByteBuffer对象引 用该内存,
避免java堆和Native堆来回复制数据,提高性能
-XX:MaxDirectMemorySize参数设置该内存大小
通用型jvm监控工具:jconsole,jvisualvm,arthas
内存分析的工具:
基于dump下来的文件进行分析:heap.hprof
-XX:+HeapDumpOnOutOfMemoryError,
-XX:HeapDumpPath=D:\xxx.hprof
1.MAT
2.基于在线的heaphero.io
3.console.perfma.com
垃圾收集分析的工具:
-XX:+PrintGC, -XX:+PrintGCDetails, -XX:+PrintGCTimeStamps, -Xloggc:D:\xxxgc.log
基于垃圾收集文件,不同的垃圾收集器有不同类型的文件
1.gcviewer.jar
2.gceasy.io
3.基于docker部署 it.gcplot.com
docker run -d -p 6666:80 gcplot/gcplot 跑一个容器,然后映射到虚拟机的6666端口