从 java 6 升级到 java 7 时本机堆上出现 OutOfMemoryError
OutOfMemoryError on native heap when upgrading from java 6 to java 7
我们最近将我们的大型网络应用程序(jboss 5 上的 运行)从 java 6 升级到 java 7。
几小时内,我们看到了 OutOfMemory 错误,看起来是 运行 出的本机堆。
我们是 运行 32 位 JVM,因此限制为 4GB,而 JVM 分配了 2GB。
在 java 6 下,整个进程占用了大约 2.3GB,但是在 java 7 下,这大大增加了,我们在没有触发完整 GC 的情况下达到了 4GB 的限制,因为 Java 堆还没有满。
堆栈跟踪显示 XML 解组代码在每个请求上创建新的 SAXParserFactory,用于解压缩 jar 文件的 Inflater class 在本机堆中存储大量数据(~200,000充气机实例)。这让我觉得效率很低——新的 SAXParserFactory 和多个 Inflators。也许这是一个转移注意力的问题,但我没有 java 6 版本来比较行为。
通过 运行 每隔几个小时手动执行一次 gc,应用程序可以愉快地运行几天,没有任何问题。但这不是解决方案。
问题是为什么内存分配增加了惊人的 1.5GB,我该如何阻止这种情况发生?
我希望更新的 java 版本更高效、更快等等。但相反,我们在 JVM 中看到了内存泄漏。
无论如何,堆栈跟踪如下:
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (malloc) failed to allocate 512128 bytes for Chunk::new
# An error report file with more information is saved as:
# /opt/SP/apps/er_core/current/hs_err_pid25455.log
00:49:30,072 ERROR [[DecouplingProcessServlet]] Servlet.service() for servlet DecouplingProcessServlet threw exception
java.lang.OutOfMemoryError
at java.util.zip.Inflater.init(Native Method)
at java.util.zip.Inflater.<init>(Inflater.java:101)
at java.util.zip.ZipFile.getInflater(ZipFile.java:450)
at java.util.zip.ZipFile.getInputStream(ZipFile.java:369)
at org.jboss.virtual.plugins.context.zip.ZipFileWrapper.openStream(ZipFileWrapper.java:214)
at org.jboss.virtual.plugins.context.zip.ZipEntryContext.openStream(ZipEntryContext.java:1066)
at org.jboss.virtual.plugins.context.zip.ZipEntryHandler.openStream(ZipEntryHandler.java:153)
at org.jboss.virtual.VirtualFile.openStream(VirtualFile.java:230)
at org.jboss.virtual.plugins.vfs.VirtualFileURLConnection.getInputStream(VirtualFileURLConnection.java:93)
at java.net.URLClassLoader.getResourceAsStream(URLClassLoader.java:233)
at javax.xml.parsers.SecuritySupport.run(SecuritySupport.java:94)
at java.security.AccessController.doPrivileged(Native Method)
at javax.xml.parsers.SecuritySupport.getResourceAsStream(SecuritySupport.java:87)
at javax.xml.parsers.FactoryFinder.findJarServiceProvider(FactoryFinder.java:283)
at javax.xml.parsers.FactoryFinder.find(FactoryFinder.java:255)
at javax.xml.parsers.SAXParserFactory.newInstance(SAXParserFactory.java:126)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.getXMLReader(AbstractUnmarshallerImpl.java:100)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:204)
at com.mycompany.global.er.decoupling.util.xml.JAXBHelper.bind(JAXBHelper.java:88)
at com.mycompany.global.er.decoupling.util.xml.JAXBHelper.bind(JAXBHelper.java:56)
at com.mycompany.global.er.decoupling.DecouplingProcessServlet.doPost(DecouplingProcessServlet.java:163)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
at org.apache.catalina.valves.RequestFilterValve.process(RequestFilterValve.java:269)
at org.apache.catalina.valves.RemoteAddrValve.invoke(RemoteAddrValve.java:81)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at pk.vodafone.valves.PKAccessLogValve.invoke(PKAccessLogValve.java:547)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:724)
00:49:30,117 ERROR [CoyoteAdapter] An exception or error occurred in the container during the request processing
java.lang.NoClassDefFoundError: javax/servlet/ServletRequestAttributeEvent
at org.apache.catalina.connector.Request.setAttribute(Request.java:1452)
at org.apache.catalina.core.StandardWrapperValve.exception(StandardWrapperValve.java:523)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:280)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
at org.apache.catalina.valves.RequestFilterValve.process(RequestFilterValve.java:269)
at org.apache.catalina.valves.RemoteAddrValve.invoke(RemoteAddrValve.java:81)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at pk.vodafone.valves.PKAccessLogValve.invoke(PKAccessLogValve.java:547)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:724)
Caused by: java.lang.ClassNotFoundException: Unexpected error during load of: javax.servlet.ServletRequestAttributeEvent, msg=null
at org.jboss.classloader.spi.base.ClassLoaderManager.process(ClassLoaderManager.java:173)
at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:259)
at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:1102)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClassFromDomain(BaseClassLoader.java:772)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClass(BaseClassLoader.java:415)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 19 more
Caused by: java.lang.OutOfMemoryError
at java.util.zip.Inflater.init(Native Method)
at java.util.zip.Inflater.<init>(Inflater.java:101)
at java.util.zip.ZipFile.getInflater(ZipFile.java:450)
at java.util.zip.ZipFile.getInputStream(ZipFile.java:369)
at org.jboss.virtual.plugins.context.zip.ZipFileWrapper.openStream(ZipFileWrapper.java:214)
at org.jboss.virtual.plugins.context.zip.ZipEntryContext.openStream(ZipEntryContext.java:1066)
at org.jboss.virtual.plugins.context.zip.ZipEntryHandler.openStream(ZipEntryHandler.java:153)
at org.jboss.virtual.VirtualFile.openStream(VirtualFile.java:230)
at org.jboss.classloading.spi.vfs.policy.VFSClassLoaderPolicy.getResourceAsStream(VFSClassLoaderPolicy.java:483)
at org.jboss.classloader.spi.base.BaseClassLoader.run(BaseClassLoader.java:508)
at org.jboss.classloader.spi.base.BaseClassLoader.run(BaseClassLoader.java:506)
at java.security.AccessController.doPrivileged(Native Method)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClassLocally(BaseClassLoader.java:504)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClassLocally(BaseClassLoader.java:481)
at org.jboss.classloader.spi.base.BaseDelegateLoader.loadClass(BaseDelegateLoader.java:134)
at org.jboss.classloader.spi.filter.FilteredDelegateLoader.loadClass(FilteredDelegateLoader.java:131)
at org.jboss.classloader.spi.base.ClassLoadingTask$ThreadTask.run(ClassLoadingTask.java:452)
at org.jboss.classloader.spi.base.ClassLoaderManager.nextTask(ClassLoaderManager.java:258)
at org.jboss.classloader.spi.base.ClassLoaderManager.process(ClassLoaderManager.java:152)
... 24 more
[thread 123611 also had an error]
我在这个主题上找到了几个有用的链接:
http://practicalcloudcomputing.com/post/444939181/outofmemoryjnigzip
http://www.javacodegeeks.com/2013/01/java-heap-space-native-heap-and-memory-problems.html
JVM选项如下:
-server -Xms2048m -Xmx2048m -XX:NewSize=384m
-XX:MaxNewSize=384m
-XX:SurvivorRatio=4
-XX:MinHeapFreeRatio=11
-XX:PermSize=80m
-verbose:gc
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
-XX:+DisableExplicitGC
-Djava.awt.headless=TRUE -DUseSunHttpHandler=TRUE -Dsun.net.client.defaultConnectTimeout=25000
-Dsun.net.client.defaultReadTimeout=50000
-Dfile.encoding=UTF-8
-Xloggc:gc.log
Dcom.sun.management.jmxremote.port=9003
-Dcom.sun.management.jmxremote.authenticate=FALSE
-Dcom.sun.management.jmxremote.ssl=FALSE
-Duser.language=de
-Duser.region=DE
-Duser.country=DE
-Djboss.vfs.cache.TimedPolicyCaching.lifetime=1440000
-DVFjavaWL=er.core.de
更新
多一点分析。这是我对 xml 解析发生的事情的天真解释:
- 我们有一个单例
JAXBHelper
class,具有实例级 JAXBContext
(这是一个线程安全对象)。
- 每次收到请求时,我们都会尝试将传入的 xml 字符串绑定到 Java 对象(之前由 JAXB 从 xsd 生成)。
- bind 方法创建一个实例级解组器(这些不是线程安全的,但创建起来很便宜)。
- 绑定方法然后调用解组程序的
unmarshal(InputStream)
方法。
- 现在
javax.xml.bind.helpers.AbstractUnmarshallerImpl
然后调用 SAXParserFactory.newInstance
,后者又调用 class 加载程序,后者又需要 Inflater
。
实现(我们使用的是 jaxb-ri 2.2.7)肯定应该保留 SAXParserFactory 或 SAXParser 并重新使用它们吗?我注意到两者都不是线程安全的,因此可以使用 ThreadLocal
来完成。或者可以重新使用 Inflater
个实例吗?
这些没有被重新使用的事实是否意味着我没有取消引用我的对象? UnMarshaller
似乎没有任何一种关闭方法。
内存泄漏是由未关闭的充气器引起的。
看起来这些膨胀器落到了老年代,只要不触发 Full GC,它们的终结器就不会被调用。
为了防止 JRE 扫描所有 JAR 文件以查找 SAXParserFactory,您可以创建包含以下行的 $JAVA_HOME/jre/lib/jaxp.properties
文件:
javax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
删除 -XX:+DisableExplicitGC
选项可能也很有用,因为 JVM 运行时在检测到本机内存不足时依赖于 System.gc
调用。
我们最近将我们的大型网络应用程序(jboss 5 上的 运行)从 java 6 升级到 java 7。
几小时内,我们看到了 OutOfMemory 错误,看起来是 运行 出的本机堆。
我们是 运行 32 位 JVM,因此限制为 4GB,而 JVM 分配了 2GB。
在 java 6 下,整个进程占用了大约 2.3GB,但是在 java 7 下,这大大增加了,我们在没有触发完整 GC 的情况下达到了 4GB 的限制,因为 Java 堆还没有满。
堆栈跟踪显示 XML 解组代码在每个请求上创建新的 SAXParserFactory,用于解压缩 jar 文件的 Inflater class 在本机堆中存储大量数据(~200,000充气机实例)。这让我觉得效率很低——新的 SAXParserFactory 和多个 Inflators。也许这是一个转移注意力的问题,但我没有 java 6 版本来比较行为。
通过 运行 每隔几个小时手动执行一次 gc,应用程序可以愉快地运行几天,没有任何问题。但这不是解决方案。
问题是为什么内存分配增加了惊人的 1.5GB,我该如何阻止这种情况发生?
我希望更新的 java 版本更高效、更快等等。但相反,我们在 JVM 中看到了内存泄漏。
无论如何,堆栈跟踪如下:
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (malloc) failed to allocate 512128 bytes for Chunk::new
# An error report file with more information is saved as:
# /opt/SP/apps/er_core/current/hs_err_pid25455.log
00:49:30,072 ERROR [[DecouplingProcessServlet]] Servlet.service() for servlet DecouplingProcessServlet threw exception
java.lang.OutOfMemoryError
at java.util.zip.Inflater.init(Native Method)
at java.util.zip.Inflater.<init>(Inflater.java:101)
at java.util.zip.ZipFile.getInflater(ZipFile.java:450)
at java.util.zip.ZipFile.getInputStream(ZipFile.java:369)
at org.jboss.virtual.plugins.context.zip.ZipFileWrapper.openStream(ZipFileWrapper.java:214)
at org.jboss.virtual.plugins.context.zip.ZipEntryContext.openStream(ZipEntryContext.java:1066)
at org.jboss.virtual.plugins.context.zip.ZipEntryHandler.openStream(ZipEntryHandler.java:153)
at org.jboss.virtual.VirtualFile.openStream(VirtualFile.java:230)
at org.jboss.virtual.plugins.vfs.VirtualFileURLConnection.getInputStream(VirtualFileURLConnection.java:93)
at java.net.URLClassLoader.getResourceAsStream(URLClassLoader.java:233)
at javax.xml.parsers.SecuritySupport.run(SecuritySupport.java:94)
at java.security.AccessController.doPrivileged(Native Method)
at javax.xml.parsers.SecuritySupport.getResourceAsStream(SecuritySupport.java:87)
at javax.xml.parsers.FactoryFinder.findJarServiceProvider(FactoryFinder.java:283)
at javax.xml.parsers.FactoryFinder.find(FactoryFinder.java:255)
at javax.xml.parsers.SAXParserFactory.newInstance(SAXParserFactory.java:126)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.getXMLReader(AbstractUnmarshallerImpl.java:100)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:204)
at com.mycompany.global.er.decoupling.util.xml.JAXBHelper.bind(JAXBHelper.java:88)
at com.mycompany.global.er.decoupling.util.xml.JAXBHelper.bind(JAXBHelper.java:56)
at com.mycompany.global.er.decoupling.DecouplingProcessServlet.doPost(DecouplingProcessServlet.java:163)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
at org.apache.catalina.valves.RequestFilterValve.process(RequestFilterValve.java:269)
at org.apache.catalina.valves.RemoteAddrValve.invoke(RemoteAddrValve.java:81)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at pk.vodafone.valves.PKAccessLogValve.invoke(PKAccessLogValve.java:547)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:724)
00:49:30,117 ERROR [CoyoteAdapter] An exception or error occurred in the container during the request processing
java.lang.NoClassDefFoundError: javax/servlet/ServletRequestAttributeEvent
at org.apache.catalina.connector.Request.setAttribute(Request.java:1452)
at org.apache.catalina.core.StandardWrapperValve.exception(StandardWrapperValve.java:523)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:280)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
at org.apache.catalina.valves.RequestFilterValve.process(RequestFilterValve.java:269)
at org.apache.catalina.valves.RemoteAddrValve.invoke(RemoteAddrValve.java:81)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at pk.vodafone.valves.PKAccessLogValve.invoke(PKAccessLogValve.java:547)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:724)
Caused by: java.lang.ClassNotFoundException: Unexpected error during load of: javax.servlet.ServletRequestAttributeEvent, msg=null
at org.jboss.classloader.spi.base.ClassLoaderManager.process(ClassLoaderManager.java:173)
at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:259)
at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:1102)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClassFromDomain(BaseClassLoader.java:772)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClass(BaseClassLoader.java:415)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 19 more
Caused by: java.lang.OutOfMemoryError
at java.util.zip.Inflater.init(Native Method)
at java.util.zip.Inflater.<init>(Inflater.java:101)
at java.util.zip.ZipFile.getInflater(ZipFile.java:450)
at java.util.zip.ZipFile.getInputStream(ZipFile.java:369)
at org.jboss.virtual.plugins.context.zip.ZipFileWrapper.openStream(ZipFileWrapper.java:214)
at org.jboss.virtual.plugins.context.zip.ZipEntryContext.openStream(ZipEntryContext.java:1066)
at org.jboss.virtual.plugins.context.zip.ZipEntryHandler.openStream(ZipEntryHandler.java:153)
at org.jboss.virtual.VirtualFile.openStream(VirtualFile.java:230)
at org.jboss.classloading.spi.vfs.policy.VFSClassLoaderPolicy.getResourceAsStream(VFSClassLoaderPolicy.java:483)
at org.jboss.classloader.spi.base.BaseClassLoader.run(BaseClassLoader.java:508)
at org.jboss.classloader.spi.base.BaseClassLoader.run(BaseClassLoader.java:506)
at java.security.AccessController.doPrivileged(Native Method)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClassLocally(BaseClassLoader.java:504)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClassLocally(BaseClassLoader.java:481)
at org.jboss.classloader.spi.base.BaseDelegateLoader.loadClass(BaseDelegateLoader.java:134)
at org.jboss.classloader.spi.filter.FilteredDelegateLoader.loadClass(FilteredDelegateLoader.java:131)
at org.jboss.classloader.spi.base.ClassLoadingTask$ThreadTask.run(ClassLoadingTask.java:452)
at org.jboss.classloader.spi.base.ClassLoaderManager.nextTask(ClassLoaderManager.java:258)
at org.jboss.classloader.spi.base.ClassLoaderManager.process(ClassLoaderManager.java:152)
... 24 more
[thread 123611 also had an error]
我在这个主题上找到了几个有用的链接:
http://practicalcloudcomputing.com/post/444939181/outofmemoryjnigzip
http://www.javacodegeeks.com/2013/01/java-heap-space-native-heap-and-memory-problems.html
JVM选项如下:
-server -Xms2048m -Xmx2048m -XX:NewSize=384m
-XX:MaxNewSize=384m
-XX:SurvivorRatio=4
-XX:MinHeapFreeRatio=11
-XX:PermSize=80m
-verbose:gc
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
-XX:+DisableExplicitGC
-Djava.awt.headless=TRUE -DUseSunHttpHandler=TRUE -Dsun.net.client.defaultConnectTimeout=25000
-Dsun.net.client.defaultReadTimeout=50000
-Dfile.encoding=UTF-8
-Xloggc:gc.log
Dcom.sun.management.jmxremote.port=9003
-Dcom.sun.management.jmxremote.authenticate=FALSE
-Dcom.sun.management.jmxremote.ssl=FALSE
-Duser.language=de
-Duser.region=DE
-Duser.country=DE
-Djboss.vfs.cache.TimedPolicyCaching.lifetime=1440000
-DVFjavaWL=er.core.de
更新
多一点分析。这是我对 xml 解析发生的事情的天真解释:
- 我们有一个单例
JAXBHelper
class,具有实例级JAXBContext
(这是一个线程安全对象)。 - 每次收到请求时,我们都会尝试将传入的 xml 字符串绑定到 Java 对象(之前由 JAXB 从 xsd 生成)。
- bind 方法创建一个实例级解组器(这些不是线程安全的,但创建起来很便宜)。
- 绑定方法然后调用解组程序的
unmarshal(InputStream)
方法。 - 现在
javax.xml.bind.helpers.AbstractUnmarshallerImpl
然后调用SAXParserFactory.newInstance
,后者又调用 class 加载程序,后者又需要Inflater
。
实现(我们使用的是 jaxb-ri 2.2.7)肯定应该保留 SAXParserFactory 或 SAXParser 并重新使用它们吗?我注意到两者都不是线程安全的,因此可以使用 ThreadLocal
来完成。或者可以重新使用 Inflater
个实例吗?
这些没有被重新使用的事实是否意味着我没有取消引用我的对象? UnMarshaller
似乎没有任何一种关闭方法。
内存泄漏是由未关闭的充气器引起的。
看起来这些膨胀器落到了老年代,只要不触发 Full GC,它们的终结器就不会被调用。
为了防止 JRE 扫描所有 JAR 文件以查找 SAXParserFactory,您可以创建包含以下行的 $JAVA_HOME/jre/lib/jaxp.properties
文件:
javax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
删除 -XX:+DisableExplicitGC
选项可能也很有用,因为 JVM 运行时在检测到本机内存不足时依赖于 System.gc
调用。