1

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

错误的堆栈tarce在这里:

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 调用都会将一些数据添加到我的容器的堆中。并且在某些时候它的大小超过了。

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

4

2 回答 2

3

失败的调用是

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

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

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

于 2009-01-28T13:54:16.643 回答
3

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

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

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 参数以了解如何增加它。

于 2009-01-28T13:54:50.950 回答