java.lang.OutOfMemoryError: GC overhead limit exceeded

目录

问题描述

运行环境

原因分析

报错原因

JVM参数

JVM内存的三个主要的域

问题解决


参考:

java.lang.OutOfMemoryError及解决方案

https://blog.csdn.net/qq_33429968/article/details/54095295

https://blog.csdn.net/renfufei/article/details/77585294


问题描述

项目部署后,启动Wildfly报错:

2019-01-03 08:44:45,919 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-2) MSC000001: Failed to start service jboss.deployment.unit."E-IDEAS.war".WeldStartService: org.jboss.msc.service.StartException in service jboss.deployment.unit."E-IDEAS.war".WeldStartService: Failed to start service
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1904)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: org.jboss.weld.exceptions.DeploymentException: Exception List with 1 exceptions:
Exception 0 :
javax.enterprise.event.ObserverException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.lang.Class.newInstance(Class.java:442)
	at org.jboss.weld.security.NewInstanceAction.run(NewInstanceAction.java:33)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.jboss.weld.injection.Exceptions.rethrowException(Exceptions.java:40)
	at org.jboss.weld.injection.Exceptions.rethrowException(Exceptions.java:78)
	at org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:96)
	at org.jboss.weld.injection.MethodInvocationStrategy$SpecialParamPlusBeanManagerStrategy.invoke(MethodInvocationStrategy.java:144)
	at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:309)
	at org.jboss.weld.event.ExtensionObserverMethodImpl.sendEvent(ExtensionObserverMethodImpl.java:124)
	at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:287)
	at org.jboss.weld.event.ObserverMethodImpl.notify(ObserverMethodImpl.java:265)
	at org.jboss.weld.event.ObserverNotifier.notifySyncObservers(ObserverNotifier.java:271)
	at org.jboss.weld.event.ObserverNotifier.notify(ObserverNotifier.java:260)
	at org.jboss.weld.event.ObserverNotifier.fireEvent(ObserverNotifier.java:154)
	at org.jboss.weld.event.ObserverNotifier.fireEvent(ObserverNotifier.java:148)
	at org.jboss.weld.bootstrap.events.AbstractContainerEvent.fire(AbstractContainerEvent.java:53)
	at org.jboss.weld.bootstrap.events.AbstractDeploymentContainerEvent.fire(AbstractDeploymentContainerEvent.java:35)
	at org.jboss.weld.bootstrap.events.AfterDeploymentValidationImpl.fire(AfterDeploymentValidationImpl.java:28)
	at org.jboss.weld.bootstrap.WeldStartup.validateBeans(WeldStartup.java:450)
	at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:90)
	at org.jboss.as.weld.WeldStartService.start(WeldStartService.java:94)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1948)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1881)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded
	at com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer.(XMLLimitAnalyzer.java:104)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.reset(XMLEntityManager.java:1546)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.reset(XMLEntityManager.java:1535)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.resetCommon(XML11Configuration.java:1016)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:803)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
	at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243)
	at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339)
	at org.apache.ibatis.parsing.XPathParser.createDocument(XPathParser.java:254)
	at org.apache.ibatis.parsing.XPathParser.(XPathParser.java:125)
	at org.apache.ibatis.builder.xml.XMLMapperBuilder.(XMLMapperBuilder.java:78)
	at org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement(XMLConfigBuilder.java:321)
	at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:107)
	at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:92)
	at org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl.parseMybatisConfiguration(ProcessEngineConfigurationImpl.java:776)
	at org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl.initMybatisConfiguration(ProcessEngineConfigurationImpl.java:759)
	at org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl.initSqlSessionFactory(ProcessEngineConfigurationImpl.java:740)
	at org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl.init(ProcessEngineConfigurationImpl.java:470)
	at org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl.buildProcessEngine(ProcessEngineConfigurationImpl.java:440)
	at com.zuccess.platform.core.activiti.SysProcessEngineLookup.getProcessEngine(SysProcessEngineLookup.java:11)
	at org.activiti.cdi.impl.ActivitiExtension.lookupProcessEngine(ActivitiExtension.java:95)
	at org.activiti.cdi.impl.ActivitiExtension.afterDeploymentValidation(ActivitiExtension.java:68)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:88)
	at org.jboss.weld.injection.MethodInvocationStrategy$SpecialParamPlusBeanManagerStrategy.invoke(MethodInvocationStrategy.java:144)
	at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:309)
	at org.jboss.weld.event.ExtensionObserverMethodImpl.sendEvent(ExtensionObserverMethodImpl.java:124)
	at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:287)

	at org.jboss.weld.bootstrap.events.AbstractDeploymentContainerEvent.fire(AbstractDeploymentContainerEvent.java:37)
	at org.jboss.weld.bootstrap.events.AfterDeploymentValidationImpl.fire(AfterDeploymentValidationImpl.java:28)
	at org.jboss.weld.bootstrap.WeldStartup.validateBeans(WeldStartup.java:450)
	at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:90)
	at org.jboss.as.weld.WeldStartService.start(WeldStartService.java:94)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1948)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1881)
	... 3 more

运行环境

wildfly9.0.0 + cdi + EclipseLink

原因分析

报错关键字

java.lang.OutOfMemoryError,即内存溢出,主要是因为需求资源超出JVM的可用资源,导致报错。

报错原因

在很多情况下都会出现java.lang.OutOfMemoryError报错,具体原因通过资料得知,主要有以下两种:

  • 外因:

程序的内存太大(比如class文件太多、lib下的jar文件太多等等)或者逻辑有误,导致程序的运行内存过大,超出限制。

  • 内因:

内因多是由于wildfly的启动参数造成的,比如JVM的初始内存、JVM的最大内存等问题。

JVM参数

JVM启动参数共分为三类:

  • 标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容; 
  • 非标准参数(-X),指的是JVM底层的一些配置参数,这些参数在一般开发中默认即可,不需要任何配置。但是在生产环境中,并不保证所有jvm实现都满足,所以为了提高性能,往往需要调整这些参数,以求系统达到最佳性能。另外这些参数不保证向后兼容,也即是说“如有变更,恕不在后续版本的JDK通知”(这是官网上的原话);
  • 非Stable参数(-XX),这类参数在jvm中是不稳定的,不适合日常使用的,后续也是可能会在没有通知的情况下就直接取消了,需要慎重使用。

JVM内存的三个主要的域

三个主要域:新域、旧域以及永久域。 
JVM生成的所有新对象放在新域中。一旦对象经历了一定数量的垃圾收集循环后,便进入旧域。而在永久域中是用来存储JVM自己的反射对象的,如class和method对象,而且GC(Garbage Collection)不会在主程序运行期对永久域进行清理(主要原因)。其中新域和旧域属于堆,永久域是一个独立域并且不认为是堆的一部分。

各主要参数的作用

  •         -Xms:设置jvm内存的初始大小
  •         -Xmx:设置jvm内存的最大值
  •         -Xmn:设置新域的大小(这个似乎只对 jdk1.4来说是有效的,后来就废弃了)
  •         -Xss:设置每个线程的堆栈大小(也就是说,在相同物理内存下,减小这个值能生成更多的线程)
  •         -XX:NewRatio :设置新域与旧域之比,如-XX:NewRatio = 4就表示新域与旧域之比为1:4
  •         -XX:NewSize:设置新域的初始值
  •         -XX:MaxNewSize :设置新域的最大值
  •         -XX:PermSize:设置永久域的初始值
  •         -XX:MaxPermSize:设置永久域的最大值
  •         -XX:SurvivorRatio=n:设置新域中Eden区与两个Survivor区的比值。(Eden区主要是用来存放新生的对象,而两个 Survivor区则用来存放每次垃圾回收后存活下来的对象)

问题解决

(1)加大Heap Size:

-Xmx512m

(2)关闭JVM这个默认的策略

// 不推荐
-XX:-UseGCOverheadLimit

 我们强烈建议不要指定该选项: 因为这不能真正地解决问题,只能推迟一点 out of memory 错误发生的时间,到最后还得进行其他处理。指定这个选项, 会将原来的 java.lang.OutOfMemoryError: GC overhead limit exceeded 错误掩盖,变成更常见的 java.lang.OutOfMemoryError: Java heap space 错误消息。

需要注意: 有时候触发 GC overhead limit 错误的原因, 是因为分配给JVM的堆内存不足。这种情况下只需要增加堆内存大小即可。

在大多数情况下, 增加堆内存并不能解决问题。例如程序中存在内存泄漏, 增加堆内存只能推迟产生 java.lang.OutOfMemoryError: Java heap space 错误的时间。

当然, 增大堆内存, 还有可能会增加 GC pauses 的时间, 从而影响程序的 吞吐量或延迟。

如果想从根本上解决问题, 则需要排查内存分配相关的代码. 简单来说, 需要回答以下问题:

1. 哪类对象占用了最多内存?

2. 这些对象是在哪部分代码中分配的。

你可能感兴趣的:(错误日志)