java 溢出异常_java内存区域及溢出异常

内存划分:

java虚拟机在执行java程序过程中会把内存分为以下区域进行管理

4dbd5b16f1467c12edf60f59048f479d.png

线程私有的

虚拟机栈

局部变量表

基本数据类型

long和double占用两个slot

对象引用

返回地址

操作数栈

动态链接

方法出口等信息

抛出异常:

栈深度过大 StackOverflowError

申请内存空间不足 OutOfMemoryError

程序计数器

本地方法栈

线程共享的

虚拟机启东时创建

方法区

常量池的回收和类型的卸载

运行常量池:字面量和符号引用 翻译出来的直接引用

直接内存

NIO可以使用Native函数库直接分配,这样能显著增加效率,因为不用在java堆和native堆中复制数据

然而,分配内存时如果直接内存加java内存超过计算机物理内存限制,就会报出OutOfMemoryError

虚拟机对象:

对象的创建:

1.new定义到常量池中的一个符号

2.检查符号代表的类是否被装载 解析 初始化

如果没有,加载类

3.加载完类后,为新生对象分配内存(类加载后会确定分配的内存大小)

内存分配方法:

如果内存是规整的 指针碰撞(指针移动对象的内存大小的位置)

如果内存是交错的 空闲列表 列表记录哪些内存是可用的,分配对象实例时分配给足够大的内存给对象,并更新列表

选择哪种分配方法由java堆是否规整来决定,堆是否规整由java回收器是否采用压缩整理功能决定

分配内存的线程安全问题

对分配内存的动作进行同步处理

TLAB 本地分配缓冲区 每个线程预先分配一块内存,哪个线程要分配内存,就在哪个线程上面分配,只有在TLAB用尽并分配新的TLAB时才需要同步锁

4.内存分配之后,内存空间都初始化为零值

5.对对象进行必要设置,设置对象头(类 元数据 hashcode gc年代)

对象的布局:

对象头

运行时数据

HashCode GC分代年龄 锁状态标识 线程持有的锁 偏向线程id 偏向时间戳

类型指针

如果是数组,对象头要保存记录数组的长度信息

实例数据

虚拟机分配策略

对齐填充

hotpot虚拟机需要对象的大小是8个字节的整数倍 对象头正好是8个字节的倍数 如果实例数据没有对齐时,需要用对齐填充来补充

对象的访问定位:

引用定义在栈上,虚拟机规范没有定义引用以何种方式定位对象位置,由虚拟机自身来完成,主流访问方式两种:

1.句柄

648bbf8cb7c58864f4d3d731d404d082.png

好处:对象移动时,只需要改变句柄的实例数据指针,不需要改变栈中本地变量的指针(它指向)

2.直接指针

53faa0f79047380d10d53e021e7402b0.png

好处 速度更快,节省一次指针定位的时间

OutOfMemoryError

java堆溢出:

通过-XX:+HeapDumpOnOutOfMemoryError可以在虚拟机异常时候dump出当前堆转储快照以便事后分析

VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOutOfMemoryError

/**

**/package com.gengsc.oom;/**

* VM args:-Xss2M

*

* @author shichaogeng

*

* 2017年6月26日*/

public classJavaVMOOM {private voiddontStop() {while (true) {//...

}

}public voidStackLeakByThread() {while (true) {

Thread thread= new Thread(newRunnable() {public voidrun() {

dontStop();

}

});

thread.start();

}

}public static voidmain(String[] args) {

JavaVMOOM oom= newJavaVMOOM();

oom.StackLeakByThread();

}

}

通过不断的建立线程可以导致OutOfMemoryError

这种异常很奇特,为每个线程分配的内存越大,反而越容易产生内存溢出

这是什么原因呢,操作系统为每个进程分配内存是有限制的,减去Xms,减去MaxPermSize,剩下的就分给虚拟机栈和本地方法栈了,每个线程分配内存越大,线程数量越少,越易产生内存溢出异常

正确的处理方式就是减少java堆的大小和栈内存来换取线程数量。

方法区域和运行时常量池内存溢出:

String.intern()方法:当常量池中存在string时,返回这个字符串对象,不存在时,添加到常量池并返回字符串的引用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值