【问题标题】:Linux server runs out of java memoryLinux 服务器的 java 内存不足
【发布时间】:2012-05-06 10:44:24
【问题描述】:

寻找解决方案或一些关于如何找出问题所在的提示。

使用 VisualVM 工具查看堆转储,该工具仅显示引用被持有。我可以使用更好的工具吗?我可以从命令行运行什么来释放这些引用吗?使用 jconsole GC 不起作用,只会延长锁定约 5 天。

Linux 服务器每 10-14 天获得以下 Java OOM:

Apr 18, 2012 1:34:55 PM org.apache.jk.core.MsgContext action
WARNING: Error sending end packet
java.net.SocketException: Broken pipe
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
    at java.net.SocketOutputStream.write(SocketOutputStream.java:153)
    at org.apache.jk.common.ChannelSocket.send(ChannelSocket.java:508)
    at org.apache.jk.common.JkInputStream.endMessage(JkInputStream.java:112)
    at org.apache.jk.core.MsgContext.action(MsgContext.java:293)
    at org.apache.coyote.Response.action(Response.java:182)
    at org.apache.coyote.Response.finish(Response.java:304)
    at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:204)
    at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:282)
    at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:744)
    at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:674)
    at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:866)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
    at java.lang.Thread.run(Thread.java:636)
Apr 18, 2012 1:34:55 PM org.apache.jk.common.ChannelSocket processConnection
WARNING: processCallbacks status 2
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid20051.hprof ...
Heap dump file created [1147163590 bytes in 149.230 secs]
Apr 18, 2012 1:59:14 PM ServerCommunicatorAdmin reqIncoming
WARNING: The server has decided to close this client connection.
Apr 18, 2012 1:59:14 PM ServerCommunicatorAdmin reqIncoming
WARNING: The server has decided to close this client connection.

【问题讨论】:

  • 除非您要发送一些庞大的数据字符串,否则我怀疑问题是随着时间的推移缓慢累积,而不是某些特定原因。
  • 我过去曾使用 Eclipse 内存分析器工具对OutOfMemoryErrors 进行故障排除,但在我的情况下,这是因为一个对象持有一个 8 GB 的 SQL 结果对象。您可以尝试使用 MAT,或者如果问题是 Hot Licks 所描述的(只是增加了内存消耗),您可能必须进行实时内存监控。
  • 不过,您需要一个分析器来分析内存增长以及增长的来源。根据我在这种情况下的经验,实际上大部分增长确实来自一两个来源。但这可能适用也可能不适用于这里
  • 是的,Java 中的典型情况是,有少数区域会以某种方式保留数据(与可能存在数百个泄漏的 C 环境不同)。但通常那一把不会太多,直到你长时间运行,反复的一把会堆积成一座山。需要某种堆分析器。
  • 有没有机会在这里使用序列化对象流?

标签: java memory connection pipe out


【解决方案1】:

如果修复缓慢累积的杂乱真的对您没有帮助,您可以考虑微调您的 VM,请查看 VM args(运行 java -X)。也许其中一些对您来说很有趣(但可能只会延长时间而没有OOM异常):

-Xms 设置初始 Java 堆大小
-Xmx 设置最大 Java 堆大小
-Xss 设置java线程栈大小
-Xprof 输出cpu profiling数据

【讨论】:

    【解决方案2】:

    使用 -Xmx 设置最大堆大小,使用 -Xss 设置线程堆栈大小。要记住的重要一点是,如果您创建了很多线程,则应将堆栈大小设置为尽可能小,以最大化您可以拥有的线程数(当您尝试创建线程时会出现 OOM 错误并堆栈空间不足)。而且堆越大,线程堆栈的空间就越少。因此,您可能需要进行一些试验才能在堆和堆栈之间获得最佳分割。

    我使用具有 1Gb 内存的 Linux 服务器管理得很好(几年前,但仍然可以正常工作),堆内存为 256M,每个线程为 64K (-Xmx256m -Xss64k)。您还应该尝试命名为 -XX:+HeapDumpOnOutOfMemoryError 的标志,并使用 JMX 获取 .hprof 转储,您可以使用 Eclipse 内存分析器对其进行分析,以查看是否有任何内存泄漏。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-10-04
      • 2012-07-05
      • 2014-07-05
      • 1970-01-01
      • 2019-01-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多