JVM学习一 java内存区域和内存外溢
一 java内存区域
必不可少的一张图
举个例子
Integer i= new Integer(1);
注释:名词-局部变量空间(solt)double是占两个
1. 虚拟机栈:存放基本类型+对象引用
2.堆:存放对象实例
3.方法区:存放已被虚拟机加载的类信息,常量,静态变量,即时编辑器编译后的代码等数据,别名Non-Heap
二对象分配方式
1.指针碰撞:java堆中的内存很规整,直接找一块大小一样的内存就可以
2.空闲列表:java堆中的内存不规整,虚拟机必须维护一个列表,通过列表去记录那些内存正在用,哪些没有
注释:java堆是否规整取决于所采用的垃圾收集器是否带有压缩整理功能决定的
三 对象内存布局
以HotSpot为例:对象头(Mark Head)可以存放普通对象类型的大小,但是无法存放数组类型和class对象类型的大小
实例数据:相当中央,存放对象的具体信息
对象填充:可有可无
四 对象的访问定位
主流的方式有两种,直接指针和句柄访问
如果使用直接指针访问,那么java堆对象的布局就必须考虑如何防止访问类型的相关信息,而reference中存储的信息就是对象地址。
如果使用句柄访问,那么java堆中就必须花粉出一块内存来作为句柄池,reference中存储的对象的句柄信息,而句柄信息中包含了对象实例数据和对象类型信息的各自的具体地址信息
具体使用哪个还是根据业务场景来选择,如果是大量的对象的话,可以使用直接指针,因为少了一次查找对象实例数据的,速度还是很快的
五:内存外溢OutOfMermoryError
1. 堆,一般的报错信息都是 OutOfMermoryError:java heap space
首先检查是内存泄露还是内存外溢,根据GC Root引用链可以定位泄漏代码位置内存外溢,说明内存对象都必须还存活着,应当检查堆参数-Xmx和-Xms与机器物理内存对比,看是否可以调大,从代码上检查是否存在某些对象生命周期过长,持有状态时间过长,尝试减少程序运行时的内存消耗
2.虚拟机栈和本地方法栈(-Xoss参数是无效的,-Xss参数决定)
如果线程请求的栈深度大于虚拟机所允许的最大深度将抛出StackOverFlowError异常
如果虚拟机在扩展栈内存时无法申请到足够的内存空间将抛出OutOfMermoryError异常
当单线程的时候:Xss的参数设置减少栈的容量和定义大量的本地变量会导致StackOverflowError异常
3.方法区和运行时常量池溢出(永久代,很难清理)
可以通过 -XX:PermSize和-XX:MaxPermSize限制方法区的大小从而可以限制常量池的容量
报错信息:PermGen Space
4.本地直接内存溢出
可直接通过-XX:MaxDirectMermorySize指定,如果不指定则默认与java堆的最大值(-Xmx指定)一样
本文为原创哦