JVM 性能调优- 五种内存溢出(5)

在介绍之前先简单介绍下 直接内存(Direct Memory)和堆内存(Heap Memory):

  • 关系:

    • 直接内存并不是Java虚拟机的一部分,它是通过Java的NIO库中的ByteBuffer来分配和管理的。直接内存通常由操作系统的本地内存(Native Memory)提供支持。
    • 堆内存是Java虚拟机的一部分,用于存储Java对象。堆内存由Java虚拟机的堆内存分配器来分配和管理。
  • 区别:

    • 分配方式:直接内存是通过调用操作系统的本地内存分配函数来分配的,而堆内存是由Java虚拟机的堆内存分配器来分配的。
    • 受限性:直接内存不受Java堆大小的限制,它可以分配的内存量通常受限于操作系统本地内存的大小。而堆内存的大小受Java虚拟机的堆内存分配器和-Xmx参数的限制。
    • 垃圾回收:直接内存不受Java对象垃圾回收的影响,因此,直接内存的分配和释放不会触发Java堆的垃圾回收操作。而堆内存中的Java对象会受到Java堆的垃圾回收操作的影响。
    • 性能:直接内存的分配和释放通常比堆内存更高效,因为它直接利用了操作系统的本地内存管理机制。而堆内存的分配和释放涉及到Java虚拟机的堆内存分配器的复杂逻辑。

总结起来,直接内存和堆内存是Java中两种不同的内存区域,它们有着不同的分配方式、受限性、垃圾回收机制和性能特点。

Java 中的内存溢出是很常见的场景,除了程序计数器外,JVM内存的其他几个运行时区域都有可能发生 OutOfMemoryError(OOM)异常。下面通过一些场景来验证JVM不同内存区域造成 OOM 的情况。

内存溢出分类

内存溢出,我们可以想象一下生活中的场景,比如我们给水杯倒水,当水杯满了后,继续倒水,就会出现水溢出了。我们把水杯比作内存区域,水比作对象,当对象创建多了,又没有及时把水倒掉或者喝掉,就会越倒越多,最后水漫出来了。

JVM 性能调优- 五种内存溢出(5)_第1张图片

JVM 中最常见的两个错误就是 StackoverflowError(栈溢出) 和 OutofMemoryError(堆溢出)。而 OutOfMemoryError 又有 5 种异常。

JVM 性能调优- 五种内存溢出(5)_第2张图片

  • java.lang.OutOfMemoryError:java heap space(堆内存溢出异常)
  • java.lang.OutOfMemoryError:GC overhead limit exceeded(GC 回收时间过长)
  • java.lang.OutOfMemoryError:Direct buffer memory(直接内存异常)
  • java.lang.OutOfMemoryError:unable to create new native thread(创建线程数达到上限异常)
  • java.lang.OutOfMemoryError:Metaspace(元空间内存不足)

StackoverflowError 和 OutofMemoryError 属于 Error,如下图的类继承关系图。

JVM 性能调优- 五种内存溢出(5)_第3张图片

栈溢出异常

如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出 StackOverflowError 异常。

栈溢出的场景,最简单的方式是多次递归调用。分配的栈空间大小一般为 512 KB,如果用完了,则会抛出异常。

编写代码

package com.test;

public class TestStackOverflowError {
    public static void main(String[] args) {
        stackOverflowError();
    }

    private static void stackOverflowError() {
        stackOverflowError();
    }
}

运行程序

你可能感兴趣的:(jvm性能调优,jvm调优,java,内存溢出)