-9

我有一个服务器通过套接字处理请求并产生一个线程来处理每个请求。

为什么我会得到一个java.lang.OutOfMemoryError,我能做些什么来解决它?

4

2 回答 2

2

类型 I:堆空间不足。

这是最常见的错误。它可能很难追踪,因为它涉及了解哪些对象是“正常的”以及应该释放哪些对象。

创建无限数量的引用对象。创建特定于线程但被另一个全局对象引用的对象。

如果您可以重现该问题,请运行jmap -dump:format=b,file=output.bin

然后用jhat.

类型 II:进程外内存

如果您已经实现了 JNI 调用,或者有由创建 JNI 对象的 JVM 代表您创建的对象,您可能会用完进程内存,对于 32 位进程来说,这是 4 gig。

正在运行的 java 进程的进程空间包括:

  • jvm内存
  • 加载的库
  • 本机创建的对象

其中-Xmx只控制JVM内存的大小。

类型 III:垃圾收集器不运行

我在任何网络搜索中都没有找到任何关于这种情况的参考。我想我已经阅读了每个帖子以解决问题java.lang.OutOfMemoryErrors

如果您有一个 Java 程序对本机代码进行 JNI 调用,那么当任何线程处于 JNI 调用中时,垃圾收集器不会运行。给定一个足够繁忙的系统,在一个 JNI 调用中有两个或更多线程,垃圾收集器可能永远不会运行。

第一个实例是一个长时间运行的 JNI 调用,它对 java 代码进行回调以释放当前对象并获取新对象。在每次迭代中,使用的内存量都会增加,并且未使用的对象不会被垃圾收集。

第二个实例是一个测试,其中每个生成的线程都会导致 JNI 调用。代码会运行很长时间,大约一个小时左右,但会以java.lang.OutOfMemoryError. 该-Xloggc选项显示前 4000 秒的定期垃圾收集,直到运行的并发线程数增加。

4055.330: [GC 4055.330: [ParNew: 147424K->12220K(147456K), 0.0073372 secs] 769563K->637289K(1294336K) icms_dc=0 , 0.0073809 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]  
18668.710: [GC 18668.710: [ParNew: 143289K->16384K(147456K), 0.0297121 secs] 768358K->651851K(1294336K) icms_dc=0 , 0.0297604 secs]

[2014 年 6 月 7 日更新] 在一个实例中,我发现了这个答案Memory leak when calling java code from C using JNI fix了这个问题。本地 java 内存分配给 C 堆栈,即使它是在 java 中分配的,因为它是从 JNI 调用内部创建的。具体来说,我使用 PushLocalFrame()/PopLocalFrame() 包装了对 java 的回调用以解决此问题。

于 2013-04-20T02:40:16.883 回答
2

发生内存不足时强制进行堆转储。请参阅我可以强制生成 JVM 崩溃日志文件吗?. 然后使用那里列出的工具来缩小内存泄漏: 分析大型 Java 堆转储的工具

于 2013-04-20T02:42:41.413 回答