什么类型的连接“RMI TCP连接(空闲)”线程对应?

时间:2012-06-06 11:42:04

标签: java rmi

我正在使用基于RMI的分布式系统,使用jdk1.6。

有时,当RMI运行时无法序列化对象时,我会在该线程上看到ConcurrentModificationException错误。我可以通过同时更新从远程方法返回的对象来轻松地重现该异常。

但问题是我无法找到这些电话的来源。 RMI异常写入stderr(在退出远程对象方法后在运行时代码中在服务器端捕获),但客户端服务中没有匹配的异常(如果这是合法的远程调用,RemoteException将提出适当的原因。)

关于这些异常的唯一不同之处在于它们发生在“RMI TCP连接(空闲)”线程上,而不是发生在诸如“RMI TCP连接(<连接计数>) - <客户端端点信息>”之类的线程上。

有关RMI中那些“空闲”线程的任何线索?我没有在openjdk源代码中找到这样的内容。

更新:我正在添加一个异常堆栈跟踪,这是您在描述的情况下通常会看到的。

服务器端控制台显示:

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$1.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 个答案:

答案 0 :(得分:4)

在RMI的连接池中创建线程,名称为“RMI TCP连接(空闲)”。当使用其中一个时,runnable用于执行将线程重命名为'RMI TCP Connection(n)',其中n是正在处理的连接号(序号),并重命名为'在runnable的最后块中空闲'。因此,任何标记为“RMI TCP连接(空闲)”的跟踪必须在runnable将其重命名为连接线程之前,或者在重命名之后。

不要问我这是怎么可能的。如果不是你的问题,问题的实际答案是在同时返回对象时不修改对象; - )

答案 1 :(得分:1)

我到底了。在两种情况下会出现问题:

  1. 当编组返回值时抛出一些异常,而该异常又包含一个易于并发修改的对象。 UnicastServerRef尝试将原因写入(已损坏的)返回流并导致ConcurrentModificationException
  2. 当方法引发异常时,此异常无法使用ConcurrentModificationException(或任何其他运行时异常)进行序列化。
    这个异常一直在堆栈中,并由线程池捕获并记录,而不是RMI运行时(这就是为什么开头没有Exception dispatching call to行)。这说明线程名称处于空闲状态,因为它已经从RMI的角度返回到池中。
  3. 这是真正的异常,实际上与第一行和实际呼叫追踪方面的再现异常有所不同:

    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$1.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)
    

    它没有提供原始问题的大量线索,因此我将不得不等待客户端异常出现在某个时刻来解决这个问题。
    如果在jconsole读取JMX属性时发生了这种异常,它将不会显示堆栈跟踪,但会将属性值显示为“不可用”。