微信号:importnew

介绍:伯乐在线旗下账号,专注Java技术分享,包括Java基础技术、进阶技能、架构设计和Java技术领域动态等.

如何修复Java中的VirtualMachineError

2019-01-27 11:30 ImportNew

(给ImportNew加星标,提高Java技能)


来自:唐尤华

译自:https://jaxenter.com/java-virtual-machine-error-154691.html


即使是最好的代码也会抛出错误,对开发人员而言这意味着需要知道如何修复它们。在这篇文章中,Ram Lakshmanan 介绍了许多不同类型的 VirtualMachineError 以及如何解决这些问题,在应用程序不崩溃的前提下回到正常状态。


当 Java 虚拟机遇到内部错误或资源限制无法运行时,就会抛出 Java.lang.VirtualMachineError。它是 JVM 的一种自我防御机制,用于防止整个应用程序崩溃。 在本文中,我将讨论许多不同类型的 VirtualMachineError,它们各自的特点、各种触发原因、以及几种可能的修复方案。


1. VirtualMachineError 的类型


有四种不同类型的 VirtualMachineError:


  1. OutOfMemoryError

  2. StackOverflowError

  3. InternalError

  4. UnknownError


让我们在本节中详细回顾这些类型。


Java throwable 类层次结构


1.1 OutOfMemoryError


就像 OMG(Oh My God)的首字母缩写一样,OOM(OutOfMemoryError)在 DevOps 社区中非常流行。 虽然大多数 DevOps 的工程师可能认为只有一种 OutOfMemoryError,但实际上 OutOfMemoryError 有八种不同类型:


  • java.lang.OutOfMemoryError:Java 堆空间

  • java.lang.OutOfMemoryError:GC 开销超过限制

  • java.lang.OutOfMemoryError:请求的数组大小超过虚拟机限制

  • java.lang.OutOfMemoryError:Permgen 空间

  • java.lang.OutOfMemoryError:Metaspace

  • java.lang.OutOfMemoryError:无法新建本机线程

  • java.lang.OutOfMemoryError:杀死进程或子进

  • java.lang.OutOfMemoryError:发生 stack_trace_with_native_method


触发每种错误的原因各有不同。类似地,根据 OutOfMemoryError 不同的问题类型,对应的解决方案也不一样。这里有一份很好的文档,用一页纸总结了所有不同类型的 OutOfMemoryError、触发原因和解决方案。


通常可以通过分析垃圾回收日志和堆转储文件来诊断和修复 OutOfMemoryError 错误。手动分析垃圾回收日志可能会很乏味,可以考虑使用免费工具,如 GCeasy、HP Jmeter 或 IBM GC analyzer。 类似地,也可以考虑使用 HeapHero 或 Eclipse MAT 这样的免费工具来分析堆转储文件。


参见:StackOverFlowError:原因及解决方案


1.2 StackOverflowError


线程的堆栈存储了执行的方法、基本数据类型值、局部变量、对象指针和返回值信息,所有这些都会消耗内存。如果线程的堆栈大小超过了内存分配限制,那么就会抛出 java.lang.StackOverflowError。通常由于执行程序中有一个错误,在线程重复递归调用同一个函数时会发生这个问题。关于如何调试 StackOverflowError 的细节以及修复这个问题可能的解决方案,更多信息可以看这里。


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 可能在对象创建、数组创建、类初始化和装箱转换时同步或异步抛出。


3. 参考资源


  • StackOverFlowError 原因及解决方案:https://jaxenter.com/stackoverflowerror-causes-152027.html

  • 远程调试 Java 应用程序: https://jaxenter.com/remote-debugging-java-applications-151466.html


看完本文有收获?请转发分享给更多人

关注「ImportNew」,提升Java技能

喜欢就点「好看」呗~


 
ImportNew 更多文章 浅析几种线程安全模型 分布式、高并发、多线程,到底有什么区别? 谈谈 Tomcat 请求处理流程 如何优雅的设计 Java 异常 哥们,你们的系统架构中为什么要引入消息中间件?
猜您喜欢 TesterHome 北京沙龙第 10 期圆满结束&PPT 下载 IsTock猴尾巴指数竞猜活动 最美好的祝福,送给最特别的你 【ES6入门系列(9)】-Symbol 2017下半年顶级恶意软件家族大起底