Какому типу соединений соответствуют потоки "RMI TCP Connection(idle)"?

Я работаю над распределенной системой, которая основана на RMI, используя jdk1.6.

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

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

единственное отличие этих исключений заключается в том, что они происходят в потоке "RMI TCP Connection(idle)", а не в потоке "RMI TCP Connection()-".

любые подсказки о том, что это за "праздные" потоки в RMI? Мне не удалось найти такого в источники пакеты OpenJDK.

Upd: я добавляю трассировку стека исключений как воспроизведенную, что вы обычно видите в описанной ситуации.

консоль на стороне сервера показывает:

Exception dispatching call to [-3534448f:12f54948b7f:-7fff, 349678755005857493] in thread "RMI TCP Connection(6)-x.x.x.x" at Thu Apr 14 16:15:13 BST 2011:
java.util.ConcurrentModificationException
    at java.util.ArrayList.writeObject(ArrayList.java:573)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1469)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
    at sun.rmi.server.UnicastRef.marshalValue(UnicastRef.java:274)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:315)
    at sun.rmi.transport.Transport.run(Transport.java:159)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)

исключение размера клиента, брошенное вызывающему абоненту:

java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
    java.io.EOFException
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:173)
    at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
    at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
    at $Proxy0.getData(Unknown Source)
    at Clnt.main(Clnt.java:11)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)
Caused by: java.io.EOFException
    at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2553)
    at java.io.ObjectInputStream.skipCustomData(ObjectInputStream.java:1899)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1873)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
    at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:306)
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:155)
    ... 9 more

2 ответов


потоки создаются в пуле соединений RMI с именем " RMI TCP Connection(idle)". Когда один из них используется, runnable, который используется для выполнения, переименовывает поток в " RMI TCP Connection (n)", где n - обрабатываемый номер соединения (последовательный номер) и переименовывается в "idle" в блоке Runnable finally. Таким образом, любая трассировка с надписью "RMI TCP Connection (idle)" должна появиться до того, как runnable переименует ее в поток подключения или после того, как она была переименована спина.

Не спрашивайте меня, как это возможно. Фактический ответ на вашу проблему, если не ваш вопрос, заключается в том, чтобы не изменять объекты, пока они одновременно возвращаются ;-)


я докопался до сути. Проблема возникает в двух случаях:

  1. при маршалинге возвращаемое значение вызывает некоторое исключение, и это исключение в свою очередь содержит объект, склонный к параллельной модификации. UnicastServerRef пытается записать причину в (уже поврежденный) возвращаемый поток и вызывает ConcurrentModificationException.
  2. когда метод вызывает исключение и это исключение не удается сериализовать с ConcurrentModificationException (или любое другое исключение на этапе выполнения).
    Это исключение идет все путь вверх по стеку и пойман и зарегистрирован пулом потоков, а не RMI runtime (вот почему нет Exception dispatching call to строка в начале). Это объясняет, что имя потока простаивает, так как оно уже возвращено в пул с точки зрения RMI.

вот реальное исключение, которое на самом деле немного отличается от того, что воспроизводится исключение, в части первой линии и фактической трассировки вызовов:

Exception in thread "RMI TCP Connection(idle)" java.util.ConcurrentModificationException
 at java.util.ArrayList.writeObject(ArrayList.java:573)
 at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
 at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461)
 at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
 at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
 at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
 at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
 at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
 at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
 at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
 at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
 at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
 at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
 at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
 at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
 at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
 at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
 at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
 at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:343)
 at sun.rmi.transport.Transport.run(Transport.java:159)
 at java.security.AccessController.doPrivileged(Native Method)
 at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
 at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
 at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
 at java.lang.Thread.run(Thread.java:619)

это не дает много ключей к исходной проблеме, поэтому мне придется подождать для исключения клиента, чтобы появиться в какой-то момент, чтобы исправить это.
Если такое исключение происходит при чтении атрибута JMX jconsole, он не будет показывать stacktrace, но покажет значение атрибута как недоступное.