Java内存区域和内存溢出异常

目录

  • 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)

https://blog.csdn.net/qq_38844645/article/details/80494705

猜你喜欢

转载自www.cnblogs.com/llq1214/p/9714676.html