本文主要是介绍Java中的VirtualMachineError,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
1. VirtualMachineError 的类型
1.1 OutOfMemoryError
1.2 StackOverflowError
1.3 InternalError
1.4 UnknownError
2. 特征
2.1 非受检异常
2.2 同步模式与异步模式
1. VirtualMachineError 的类型
有四种不同类型的 VirtualMachineError:
OutOfMemoryError
StackOverflowError
InternalError
UnknownError
让我们在本节中详细回顾这些类型。
Java throwable 类层次结构
1.1 OutOfMemoryError
OOM(OutOfMemoryError)在 DevOps 社区中非常流行。 虽然大多数 DevOps 的工程师可能认为只有一种 OutOfMemoryError,但实际上 OutOfMemoryError 有九种不同类型:
- java.lang.OutOfMemoryError:在Java 堆空间中创建新的对象
- java.lang.OutOfMemoryError:GC 开销超过限制
- java.lang.OutOfMemoryError:请求的数组大小超过虚拟机限制,JVM 在为数组分配内存前,会检查要分配的数据结构在系统中是否可寻址,通常为
Integer.MAX_VALUE - 2
。 - java.lang.OutOfMemoryError:Permgen 空间(Jdk8取消该区域)
- java.lang.OutOfMemoryError:Metaspace被用满
- java.lang.OutOfMemoryError:无法创建一个新的 native 线程
- java.lang.OutOfMemoryError:杀死进程或子进程
- java.lang.OutOfMemoryError:超出默认Direct ByteBuffer大小
- java.lang.OutOfMemoryError:Out of swap space?
触发每种错误的原因各有不同。类似地,根据 OutOfMemoryError 不同的问题类型,对应的解决方案也不一样。查找OOM触发原因和解决方案,可以参考https://segmentfault.com/a/1190000019910501
通常可以通过分析垃圾回收日志和堆转储文件来诊断和修复 OutOfMemoryError 错误。手动分析垃圾回收日志可能会很乏味,可以考虑使用免费工具,如 GCeasy、HP Jmeter 或 IBM GC analyzer。 类似地,也可以考虑使用 HeapHero 或 Eclipse MAT 这样的免费工具来分析堆转储文件。
1.2 StackOverflowError
线程的堆栈存储了执行的方法、基本数据类型值、局部变量、对象指针和返回值信息,所有这些都会消耗内存。如果线程的堆栈大小超过了内存分配限制,就会抛出 java.lang.StackOverflowError。关于如何调试 StackOverflowError 的细节以及修复这个问题可能的解决方案,可以参考https://jaxenter.com/stackoverflowerror-causes-152027.html
出现StackOverflowError一般有以下两种情况:
- 方法递归调用问题,导致栈帧不断增加,无法分配新的栈帧(栈容量最小值取决于操作系统内存分页大小)
- 还有一种情况就是创建线程时,线程所需堆栈大于默认线程堆栈大小,这个时候需要调整参数-Xss<size>
1.3 InternalError
JVM 抛出 java.lang.InternalError 有三个原因,虚拟机软件出现错误、系统软件底层出现错误或者硬件出现故障。
然而,很少会遇到 InternalError 这样的错误。要了解哪些特定情况可能导致 InternalError,请在 Oracle 的 Java Bug 数据库 中搜索 InternalError。在写这篇文章的时候(2018年12月20日),Oracle Java Bug 数据库中仅报告了200个 InternalError,而且大多数都已经修复了,所以不必对此过于担心。
1.4 UnknownError
当发生异常或错误,但 Java 虚拟机无法报告确切的异常或错误时,就会抛出 java.lang.UnknownError。UnknownError 很少出现。事实上,在 Oracle Java Bug 数据库中搜索 UnknownError 时,只找到了2个 Bug。参见:远程调试 Java 应用程序
2. 特征
VirtualMachineError 有两个主要特征:
- 非受检异常(Unchecked exceptions)
- 同步模式与异步模式
让我们在本节中讨论这两个特征。
2.1 非受检异常
有两种异常类型:受检异常和非受检异常。
在编译时检查的异常称为受检异常。如果代码中的某些方法抛出受检异常,那么该方法必须处理该异常或者使用 throws 关键字指定异常。受检异常包括 IOException、SQLException、DataAccessException、ClassNotFoundException 等。
非受检异常常没有这个要求,它们不需要捕获或者声明抛出。所有类型的 VirtualMachineError 都是非受检异常。
2.2 同步模式与异步模式
可以在两种模式下抛出异常:同步模式和异步模式。
同步异常在特定程序语句执行时发生,无论该程序在类似的环境中执行了多少次。同步异常的例子有 NullPointerException、 ArrayIndexOutOfBoundException 等。
异步异常可以在任何时间点和程序语句的任何部分发生,异常抛出的地方也不一样。所有的 VirtualMachineError 都是异步抛出的,但有时也会同步抛出。StackOverflowError 可能随方法调用而同步抛出,也可能随着本地方法执行或 Java 虚拟机资源限制异步抛出。类似地,OutOfMemoryError 可能在对象创建、数组创建、类初始化和装箱转换时同步或异步抛出。
这篇关于Java中的VirtualMachineError的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!