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(无法继续申请到内存

扫描二维码关注公众号,回复: 3380688 查看本文章

直接内存

通过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