目录
- java内存区域和内存溢出异常
- 虚拟机运行时数据区
- 线程私有
- 程序计数器
- 虚拟机栈
- 本地方法栈
- 公共部分
- 堆
- 方法区
- 运行时常量池
- 直接内存
- 参考文章
- 线程私有
- 对象的创建
- 对象的内存布局
- 对象的访问定位
- 实战:OOM异常
- java堆溢出
- 虚拟机栈和本地方法栈溢出
- 虚拟机运行时数据区
虚拟机运行时数据区
线程私有
程序计数器
1.是当前线程所执行的字节码的行号指示器
2.不会有溢出
虚拟机栈
1.运行java代码的栈内存
2.会有如下异常
StackOverflowError(栈的深度大于规定深度)
OutOfMemoryError(无法继续申请到内存)
本地方法栈
1.运行本地方法栈内存
2.OutOfMemoryError(无法继续申请到内存)
公共部分
堆
1.存放几乎多有新建的对象实例
2.OutOfMemoryError(无法继续申请到内存)
方法区
1.存放编译时class(方法,属性,接口等)文件的信息
2.OutOfMemoryError(无法继续申请到内存)
运行时常量池
1.存放class文件的字面量和符号引用
2.OutOfMemoryError(无法继续申请到内存
直接内存
通过DirectByteBuffer直接引用本地的内存
对象的创建
以实例虚拟机HotSpot和常用的内存去java堆为例
代码里面通常有关键字new来创建实例
实际上,虚拟机遇到一条new命令时
1.检查这个指令的参数能否在常量池中定位到一个类的符号引用
2.有的话,检查这个符号引用代表的类是否已被加载,解析和初始化过,
如果没有,需要先进行相应的类加载过程
3.类加载检查通过后,为新生对象分配内存两种方式:
“指针碰撞”--堆内存是绝对规整的,将指针往空闲的内存偏移类的大小个内存
“空闲列表”--堆内存不规整,需要维护一个列表,记录哪些内存是可用的
堆内存是否规整,和垃圾回收期是否带有压缩整理功能决定。
4.内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头)
5.虚拟机要对对象进行必要的设置。(例如这个对象是哪个类的实例,如何才能找到类的元数据信息,对象的哈希码,对象的GC分代年龄等信息)
分配内存的时候,会有线程安全问题。
解决这个问题的两种方式:
1.将分配内存的这一操作同步处理
2.从内存的角度,利用线程。将内存分配为线程私有的,代码通过线程来操作内存。成为TLAB本地线程分配缓冲。只有TLAB用完并分配新的TLAB时,需要加同步锁定。
对象的内存布局
三部分
1.对象头
2.实例数据
3.对齐填充
对象的访问定位
两种方式
1.句柄
2.直接指针
实战:OOM异常
java堆溢出
//-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 //-verbose:gc -Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError package oom; import java.util.ArrayList; import java.util.List; public class HeapOOM { /** * -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 * @param args */ public static void main(String[] args) { List<HeapOOM> list = new ArrayList<HeapOOM>(); while(true){ list.add(new HeapOOM()); } } } [GC (Allocation Failure) 5373K->3697K(19968K), 0.0102493 secs] [GC (Allocation Failure) 9205K->8248K(19968K), 0.0127932 secs] [Full GC (Ergonomics) 17045K->12846K(19968K), 0.2904709 secs] [Full GC (Ergonomics) 16397K->16359K(19968K), 0.2465633 secs] [Full GC (Allocation Failure) 16359K->16347K(19968K), 0.1879997 secs] java.lang.OutOfMemoryError: Java heap space Dumping heap to java_pid1492.hprof ... Heap dump file created [27974970 bytes in 0.198 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3210) at java.util.Arrays.copyOf(Arrays.java:3181) at java.util.ArrayList.grow(ArrayList.java:261) at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235) at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227) at java.util.ArrayList.add(ArrayList.java:458) at oom.HeapOOM.main(HeapOOM.java:15)
虚拟机栈和本地方法栈溢出
-verbose:gc -Xss128k
package oom; public class JavaVMStackSOF { private int stackLenth = 1; public void stackLeak() { stackLenth++; stackLeak(); } public static void main(String[] args) throws Throwable { JavaVMStackSOF oom = new JavaVMStackSOF(); try { oom.stackLeak(); } catch (Throwable e) { System.out.println("stack lengt:"+oom.stackLenth); throw e; } } } stack lengt:992 Exception in thread "main" java.lang.StackOverflowError at oom.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:8) at oom.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9) at oom.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9) at oom.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9) at oom.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9) at oom.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9) at oom.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9) at oom.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9)