JVM内存区域
Posted joecqupt
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM内存区域相关的知识,希望对你有一定的参考价值。
JVM 内存划分
- 栈
- 虚拟机栈
- 本地方法栈
- 堆
- 方法计数器
- 方法区
对象的分配
- 指针碰撞
- 空闲列表 (√)
分配内存 线程安全问题:
- 分配动作处同步---实际上采用CAS保证分配的原子性
- TLAB 本地线程分配缓存
对象内存中的信息布局
- 对象头
- Mark word (根据对象状态复用此部分空间)
- hashcode
- GC分代信息
- 锁状态信息
- 线程持有的锁
- 偏向线程ID
- 偏向时间戳
- .....
- 类型指针(对象指向它的类元数据的指针,虚拟机可以通过这个指针来确定这个对象是哪一个类的实例)
- Mark word (根据对象状态复用此部分空间)
- 实例数据
- 对齐填充(对齐填充并不是必要的,只是vm要求对象的大小必须是8的整数倍,当实例数据没有对齐时,需要填充来补全。)
对象的定位:
- 使用句柄
- 优点 :对象被移动 只会改变句柄中的的指针
- 缺点 :多了一次查找
- 直接指针访问 (√)
- 优点 : 速度快
OutOfMemoryError
内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;
内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
StackOverflowError
- 如果线程申请的栈的深度大于虚拟机所允许的最大深度,抛出StackOverflowError异常
- 如果虚拟机在扩展栈时候,无法申请到足够的内存空间。抛出OutOfMemory异常
方法区与运行时常量溢出
- jdk 1.6 以及之前的版本可以使用 String.intern() 方法
- String.intern() 方法的是作用是:如果字符串常量池中已经含有此字符串那么返回此字符串的,如果不包含此字符串 那么将此 字符串实例 复制到字符串常量池中。
- jdk 1.7 版本不会将字符串 复制 字符串实例,只会记录此字符串的引用。
- jdk 1.7 只会可以使用 反射,或者字节码操作框架产生大量的Class对象来造成 方法区溢出
本地直接内存溢出 -XX:MaxDirectMemorySize=10M;
- 可以使用 UnSafe类 (没有试验成功过)
如果发生了内存溢出异常,但是dump文件看不出明显的异常,并且dump文件很小,而程序中又直接或者间接使用了NIO,那么可以考虑检查是不是这一方面的问题
以上是关于JVM内存区域的主要内容,如果未能解决你的问题,请参考以下文章