超出OutOfMemory GC开销限制,无法获取log4j对象的锁



有人能帮我确定问题的确切原因吗。它是JVM、Log4j还是我们应用程序中的其他东西?

我们正在Solaris 10(SUNW,Sun-Fire-V240)服务器上使用JDK 1.6.0.24运行一个多线程应用程序。它有RMI调用来与客户端通信。

我们的申请被挂了。我在threaddump中看到了下面的OutOfMemory。然而,我知道这是因为GC只能声明2%的对象内存。

#java.lang.OutOfMemoryError:超出GC开销限制堆PSYoungGen总计304704K,使用154560K[0xe04000,0xfbc00000,0xfbc 00000)eden空间154560K,100%使用[0xe400000,0xe9af0000,0xe9af 0000)从空间150144K,使用0%[0xf296000,0xfbc00000)到空间145856K,使用0%[0xe9af0000,0xe9af0000:0xf2960000)PSOldGen总计897024K,使用897023K[0xa9800000,0xe040000,0xe400000)对象空间897024K,99%已使用[0xa9800000,0xe03ffff0,0xe0400000)PSPermGen总计28672K,使用27225K[0xa3c00000,0xa5800000,0xa9800000)对象空间28672K,94%使用[0xa3c00000,0xa5696580,0xa5800000)

在我的情况下,这应该是因为GC无法从大量等待的线程中获取内存。如果我看到线程转储。大多数线程都在等待获取org.apache.log4j.Logger上的锁。使用log4j-1.2.15

如果您在下面看到第一个线程的跟踪。它获取了2个对象的锁,其他线程(~50个)正在等待获取锁。在20分钟内可以看到几乎相同的痕迹。

这是线程转储:

pool-3-thread-51"prio=3 tid=0x00a38000 nid=0xa4可运行[0x00d5f000]java.lang.Thread.State:可运行在java.text.DateFormat.format(DateFormat.java:316)网址:org.apache.log4j.helpers.PatternParser$DatePatternConverter.convert(PatternParser.java:443)网址:org.apache.log4j.helpers.PatternConverter.format(PatternConverter.java:65)网址:org.apache.log4j.PatternLayout.format(PatternLayout.java:506)网址:org.apache.log4j.WriterAppender.subAppend(WriterAappender.java:310)网址:org.apache.log4j.RollingFileAppender.subAppend(RollingFileApender.java:276)网址:org.apache.log4j.WriterAppender.append(WriterAappender.java:162)网址:org.apache.log4j.AppenderSketleton.doAppend(AppenderSletletleton.java:251)-锁定(org.apache.log4j.RollingFileAppender)网址:org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttahableImpl.java:66)网址:org.apache.log4j.Category.callAppenders(Category.java:206)-锁定(org.apache.log4j.Logger)网址:org.apache.log4j.Category.forcedLog(Category.java:391)网址:org.apache.log4j.Category.info(Category.java:666)网址:com.airvana.faultServer.niohandlers.NioNotificationHandler.parseAndQueueData(NioNotificationHandler.java:296)网址:com.airvana.faultServer.niohandlers.NioNotificationHandler.messageReceived(NioNotificationHandler.java:145)网址:org.jboss.nety.channel.SimpleChannelHandler.handleUpstream(SimpleChannelHandler.java:105)网址:org.jboss.nety.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPiperine.java:567)"Timer-3"prio=3 tid=0x0099a800 nid=0x53等待监视器条目[0xa1caf000]java.lang.Thread.State:BLOCKED(在对象监视器上)网址:org.apache.log4j.AppenderSketleton.doAppend(AppenderSletletleton.java:231)-等待锁定(org.apache.log4j.RollingFileAppender)网址:org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttahableImpl.java:66)网址:org.apache.log4j.Category.callAppenders(Category.java:206)-锁定(org.apache.log4j.spi.RootLogger)网址:org.apache.log4j.Category.forcedLog(Category.java:391)网址:org.apache.log4j.Category.info(Category.java:666)网址:com.airvana.controlapp.export。AbstractOMDataCollector。run(AbstractOMDataCollector。java:100)位于java.util.TimerThread.mainLoop(Timer.java:512)位于java.util.TimerThread.run(Timer.java:462)"TrapHandlerThreadPool:Thread-10"prio=3 tid=0x014dac00 nid=0x4f正在等待监视器条目[0xa1d6f000]java.lang.Thread.State:BLOCKED(在对象监视器上)网址:org.apache.log4j.AppenderSketleton.doAppend(AppenderSletletleton.java:231)-等待锁定(org.apache.log4j.RollingFileAppender)网址:org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttahableImpl.java:66)网址:org.apache.log4j.Category.callAppenders(Category.java:206)-锁定(org.apache.log4j.Logger)网址:org.apache.log4j.Category.forcedLog(Category.java:391)网址:org.apache.log4j.Category.info(Category.java:666)网址:com.airvana.faultServer.db.ConnectionPool.printDataSourceStats(ConnectionPool.java:146)网址:com.airvana.faultServer.db.SQLUtil.freeConnection(SQLUtil.java:267)网址:com.airvana.faultServer.db.DbAPI.addEventOrAlarmOptimized(DbAPI.java:904)网址:com.airvana.faultServer.eventProcessing.EventProcessor.processEvent(EventProcessor.java:24)网址:com.airvana.faultServer.filters.BasicTrapFilter.productTrap(BasicTrapFilter.java:80)网址:com.airvana.faultServer.eventEngine.eventEngine.notifyTrapProcessors(eventEngine.java:314)网址:com.airvana.faultServer.eventEngine.NodewiseTrapQueue.run(NodewiseTrapQueue.java:94)网址:com.airvana.common.utils.ThreadPool$PoolThread.run(ThreadPool.java:356)"RMI TCP连接(27927)-10.193.3.41"守护进程prio=3 tid=0x0186c800 nid=0x1d53正在等待监视器条目[0x9f84e000]java.lang.Thread.State:BLOCKED(在对象监视器上)网址:org.apache.log4j.AppenderSketleton.doAppend(AppenderSletletleton.java:231)-等待锁定(org.apache.log4j.RollingFileAppender)网址:org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttahableImpl.java:66)网址:org.apache.log4j.Category.callAppenders(Category.java:206)-锁定(org.apache.log4j.Logger)网址:org.apache.log4j.Category.forcedLog(Category.java:391)网址:org.apache.log4j.Category.info(Category.java:666)网址:com.airvana.faultServer.processCommunications.ConfigAppCommReceiver.sendEvent(ConfigAppCommReceiver.java:178)位于sun.reflect.GeneratedMethodAccessor14.invoke(未知源)在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)位于java.lang.reflect.Method.ioke(Method.java:597)位于sun.rmi.server.UnincastServerRef.dispatch(UnicastServerRef.java:305)在sun.rmi.transport.transport$1.run(transport.java:159)位于java.security.AccessController.doPrivileged(本机方法)在sun.rmi.transport.transport.serviceCall(transport.java:155)位于sun.rmi.transport.TCPTransport.handleMessages(TCPTransport.java:535)位于sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)位于sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)位于java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)位于java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)在java.lang.Thread.run(线程.java:619)"pool-3-thread-49"prio=3 tid=0x01257800 nid=0xa1正在等待监视器条目[0xa0def000]java.lang.Thread.State:BLOCKED(在对象监视器上)网址:org.apache.log4j.Category.callAppenders(Category.java:204)-等待锁定(org.apache.log4j.Logger)网址:org.apache.log4j.Category.forcedLog(Category.java:391)网址:org.apache.log4j.Category.info(Category.java:666)网址:com.airvana.faultServer.niohandlers.NioNotificationHandler.processSeqNumber(NioNotificationHandler.java:548)网址:com.airvana.faultServer.niohandlers.NioNotificationHandler.parseAndQueueData(NioNotificationHandler.java:301)网址:com.airvana.faultServer.niohandlers.NioNotificationHandler.messageReceived(NioNotificationHandler.java:145)网址:org.jboss.nety.channel.SimpleChannelHandler.handleUpstream(SimpleChannelHandler.java:105)网址:org.jboss.nety.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPiperine.java:567)网址:org.jboss.nety.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPiperine.java:803)网址:org.jboss.nety.channel.Channels.fireMessageReceived(Channels.java:385)网址:org.jboss.nety.handler.codec.frame.FrameDecoder.unfoldAndFireMessageReceived(FrameDecoder.java:324)网址:org.jboss.nety.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:306)网址:org.jboss.nety.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:223)网址:org.jboss.nety.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:87)网址:org.jboss.nety.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPiperine.java:567)网址:org.jboss.nety.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPiperine.java:803)网址:org.jboss.nety.handler.timeout.ReadTimeoutHandler.messageReceived(ReadTimeoutHandler.java:149)网址:org.jboss.nety.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:87)网址:org.jboss.nety.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPiperine.java:567)位于org.jboss.nety.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPipe"pool-3-thread-44"prio=3 tid=0x00927800 nid=0x9b正在等待监视器条目[0xa0f0f000]java.lang.Thread.State:BLOCKED(在对象监视器上)网址:org.apache.log4j.Category.callAppenders(Category.java:204)-等待锁定(org.apache.log4j.Logger)网址:org.apache.log4j.Category.forcedLog(Category.java:391)网址:org.apache.log4j.Category.info(Category.java:666)网址:com.airvana.faultServer.niohandlers.NioNotificationHandler.parseAndQueueData(NioNotificationHandler.java:296)网址:com.airvana.faultServer.niohandlers.NioNotificationHandler.messageReceived(NioNotificationHandler.java:145)网址:org.jboss.nety.channel.SimpleChannelHandler.handleUpstream(SimpleChannelHandler.java:105)网址:org.jboss.nety.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPiperine.java:567)网址:org.jboss.nety.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPiperine.java:803)网址:org.jboss.nety.channel.Channels.fireMessageReceived(Channels.java:385)网址:org.jboss.nety.handler.codec.frame.FrameDecoder.unfoldAndFireMessageReceived(FrameDecoder.java:324)网址:org.jboss.nety.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:306)网址:org.jboss.nety.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:223)网址:org.jboss.nety.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:87)网址:org.jboss.nety.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPiperine.java:567)网址:org.jboss.nety.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPiperine.java:803)网址:org.jboss.nety.handler.timeout.ReadTimeoutHandler.messageReceived(ReadTimeoutHandler.java:149)网址:org.jboss.nety.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:87)网址:org.jboss.nety.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPiperine.java:567)网址:org.jboss.nety.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPiperine.java:803)网址:org.jboss.nety.channel.Channels.fireMessageReceived(Channels.java:385)网址:org.jboss.nety.handler.codec.frame.FrameDecoder.unfoldAndFireMessageReceived(FrameDecoder.java:324)网址:org.jboss.nety.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:306)网址:org.jboss.nety.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:221)网址:org.jboss.nety.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:87)网址:org.jboss.nety.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPiperine.java:567)网址:org.jboss.nety.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPiperine.java:803)网址:org.jboss.nety.handler.execution.ChannelEventRunnable.run(ChannelEventRunable.java:76)网址:org.jboss.nety.handler.execution.OrderedMemorywareThreadPoolExecutor$ChildExecutor.run(OrderedMemoorywareThreadPoolexecutor.java:314)位于java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)位于java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)在java.lang.Thread.run(Thread.java:619)

当JVM决定运行垃圾收集器的时间百分比太大时,会发生由于GC开销限制而导致的OutOfMemoryError。这是一个典型的迹象,表明堆几乎满了。

如果堆太满,JVM将花费越来越多的时间进行垃圾收集,以回收越来越少的内存。剩下的做有用工作的时间相应减少。

我的假设是,您的记录器正在备份,因为GC运行之间没有足够的时间来处理日志记录率。因此,大量的线程被阻塞是问题的次要症状,而不是根本原因。


假设上述情况成立,短期解决方案是使用JVM选项重新启动应用程序,以获得更大的堆大小。您还可以更改GC开销阈值,以便您的应用程序更快地消亡。(这可能看起来很奇怪,但对于你的应用程序来说,最好是快速终止,而不是在几分钟或几个小时内停滞。)

真正的解决方法是找出堆空间不足的原因。您需要启用GC日志记录,并在应用程序运行时观察内存使用趋势。。。数小时、数天、数周。如果你注意到内存使用量在长期增长,那么你很可能有某种内存泄漏。您需要使用内存探查器来跟踪它。

此问题描述似乎与错误41214的描述类似。我不确定这是否与您的问题有关,但您发布的堆栈跟踪中的一些元素与该bug中的元素相似。

因此,您可能需要遵循Stephen的建议,以验证是否有来自多个线程的过多记录器调用导致大量锁争用。将记录器的级别切换到更高的级别可能会有所帮助,尽管如果您需要日志条目,这是不可取的;我建议在仔细考虑后使用。

到目前为止,我们还没有看到这个问题。

我真的不确定JDK从JDK1.6.0.20升级到JDK1.6.0.24后,问题什么时候缩小了。

最新更新