Поток RMI завершается из-за java.lang.OutOfMemoryError: пространство кучи Java - PullRequest
2 голосов
/ 28 января 2009

Я работаю над приложением на основе компа. В этом приложении существует 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 этого завершенного потока добавляет некоторые данные в кучу моего контейнера. и в определенный момент его размер превышает.

Мой вопрос к вам, ребята, заключается в том, что если не хватает памяти в размере кучи моего контейнера, почему другие потоки работают? Пожалуйста, дайте мне знать, если у вас есть идеи.

Ответы [ 2 ]

3 голосов
/ 28 января 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
...
sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) at  

Итак, поток, который не работает, пытается создать новый массив для обработки входящего запроса. Если этот массив особенно велик, обработчик запросов может быть не в состоянии выделить его, в то время как другие запросы, использующие меньшие объемы данных, будут обрабатываться без проблем.

Итак, первый вопрос: насколько велик этот массив? Вы должны поставить некоторые записи на стороне клиента, чтобы определить это. И если конкретный клиент пытается отправить исключительно большой массив, вам может потребоваться уменьшить его размер.

Второй вопрос: предоставили ли вы серверной JVM достаточно памяти для обработки ожидаемой нагрузки? Jave - одна из немногих сред, в которых все еще требуется указывать объем памяти, необходимый программе, и по умолчанию она достаточно мала (я думаю, 64M). Просмотрите параметры -ms и -mx, чтобы узнать, как его увеличить.

3 голосов
/ 28 января 2009

Неудачный вызов

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

, что означает, что сбойный поток RMI пытался выделить массив. К сожалению, это не говорит нам, насколько большой массив он пытался выделить. Если бы он пытался выделить огромный массив и потерпел неудачу, то это не повредило бы ни одному другому потоку. Есть ли что-то другое в неудавшемся запросе, что он должен был бы выделить намного больше памяти, чем другие запросы?

Для уточнения ... скажем, по какой-то причине этот один запрос пытается выделить массив размером 500 Мб (а в куче недостаточно памяти). Ну, , что запрос на выделение не удастся. Но пока куча все еще имеет достаточно памяти для обычных запросов на выделение, у других потоков не будет проблем с созданием новых объектов.

...