【问题标题】:RMI Thread terminating due to java.lang.OutOfMemoryError: Java heap space由于 java.lang.OutOfMemoryError:Java 堆空间,RMI 线程终止
【发布时间】:2009-01-28 13:43:02
【问题描述】:

我正在开发一个基于 comp 的应用程序。 在这个应用程序中,有 n 个容器通过它们相互提供的 RMI 服务相互通信。 在某些情况下,连接到我的容器的一个 rmi 线程由于内存不足错误而失去连接,但连接到我的容器的所有其他 RMI 线程都工作正常。

错误的堆栈在这里:

Exception dispatching call to [655d565c:11f1d5dbae2:-7ffb, -3259564578052694518] in thread "RMI TCP Connection(21)-132.186.96.179" at Wed Jan 28 18:50:37 GMT+05:30 2009: 
java.lang.OutOfMemoryError: Java heap space
    at java.lang.reflect.Array.newArray(Native Method)
    at java.lang.reflect.Array.newInstance(Unknown Source)
    at java.io.ObjectInputStream.readArray(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
    at java.io.ObjectInputStream.readSerialData(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
    at java.io.ObjectInputStream.readSerialData(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at sun.rmi.server.UnicastRef.unmarshalValue(Unknown Source)
    at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
    at sun.rmi.transport.Transport$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Unknown Source)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

要查看此异常,我必须激活 RMI 特定日志记录。出现此问题是因为此终止线程的每个 RMI 调用都会将一些数据添加到我的容器的堆中。 并且在某些时候它的大小超过了。

我的问题是,如果我的容器的堆大小内存不足,为什么其他线程正在工作? 如果您有任何想法,请告诉我。

【问题讨论】:

  • 这个错误是由 RMI 专门捕获的,并且具体 会导致 RMI 线程终止。看看别处。

标签: multithreading rmi


【解决方案1】:

失败的调用是

java.lang.reflect.Array.newArray(Native Method)

这意味着失败的 RMI 线程正在尝试分配一个数组。不幸的是,它没有告诉我们它试图分配的数组有多大。它试图分配一个 huge 数组,但失败了,那么这不会伤害任何其他线程。与正在发出的其他请求相比,失败的请求必须分配 更多 更多的内存,这与失败的请求有什么不同吗?

详细说明...假设出于某种原因,这个请求试图分配一个 500 兆的数组(并且堆上没有足够的内存)。那么,那个分配请求将会失败。但是只要堆还有足够的内存来处理正常的分配请求,其他线程创建新对象就不会出现问题。

【讨论】:

    【解决方案2】:

    简单的回答:因为其他操作没有失败操作的内存需求。

    更长的答案从查看堆栈跟踪开始:

    java.lang.OutOfMemoryError: Java heap space at java.lang.reflect.Array.newArray(Native Method) at
    java.lang.reflect.Array.newInstance(Unknown Source) at java.io.ObjectInputStream.readArray(Unknown Source) at
    java.io.ObjectInputStream.readObject0(Unknown Source) at java.io.ObjectInputStream.defaultReadFields(Unknown
    ...
    sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) at  
    

    因此,失败的线程正在尝试创建一个新数组,以处理传入的请求。如果该数组特别大,则请求处理程序可能无法分配它,而使用较少数据量的其他请求将毫无问题地处理。

    那么,第一个问题是:这个数组有多大?您应该在客户端放置一些日志来确定这一点。如果一个特定的客户端试图发送一个非常大的数组,你可能需要减小它的大小。

    第二个问题:您是否为服务器 JVM 提供了足够的内存来处理预期的负载? Jave 是少数仍然需要您告诉它程序需要多少内存的环境之一,而且默认值非常小(我相信是 64M)。查看 -ms 和 -mx 参数以了解如何增加它。

    【讨论】:

      猜你喜欢
      • 2010-12-08
      • 2015-05-14
      • 2019-07-10
      • 2019-12-12
      相关资源
      最近更新 更多