【问题标题】:java.rmi.UnmarshalException in RMI callRMI 调用中的 java.rmi.UnmarshalException
【发布时间】:2015-11-16 08:21:10
【问题描述】:

请注意.. 在花费了 EJP 的大量时间后,该问题已得到解决。 (诚​​挚的歉意,并深深感谢所提供的帮助。)

我们有一个客户端-服务器应用程序。通信是 RMI。我们只在应用程序中遇到了以下异常。该程序已经运行了 5 年多,但下面提到的异常最近只发生过一次。

例外是

    java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
    java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.company.server.TestImplConcrete
    at com.company.server.TopicSessionImpl_Stub.createPublisher(Unknown Source)
    at com.company.process.finance.client.transactionservers.clientClass$TailorCalcManager.calc(clientClass.java:92)
    at com.company.process.finance.client.transactionservers.clientClass$TailorCalcManager.access$500(clientClass.java:37)
    at com.company.process.finance.client.transactionservers.clientClass.processTransaction(clientClass.java:346)
    at com.company.process.finance.TransactionServer.processTransaction(TransactionServer.java:50)
    at com.company.products.server.TransactionalProductManager.processTransaction(TransactionalProductManager.java:120)
    at com.company.products.server.TransactionalProductManager.processTransaction(TransactionalProductManager.java:110)
    at com.company.process.core.Manager$BrokerListener.readITMsg(Manager.java:74)
    at com.company.core.util5.FixedSizeThreadPoolMsgBus$ParallelTask.run(FixedSizeThreadPoolMsgBus.java:37)
    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)
Caused by: java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.company.server.TestImplConcrete
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    ... 12 more
Caused by: java.io.NotSerializableException: com.company.server.TestImplConcrete
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at com.company.server.TopicSessionImpl_Skel.dispatch(Unknown Source)
    at sun.rmi.server.UnicastServerRef.oldDispatch(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.run(Unknown Source)
    ... 1 more

我浏览了一些帖子,他们建议应该将类 TestImplConcrete 设为可序列化以摆脱异常。我完全同意 TestImplConcrete 类是 序列化的。但这里的问题是,如果这是解决问题的唯一方法,那么过去 5 年班级的学习情况如何,班级如何仍然没有任何问题地工作?

注意:我们只遇到过一次这个问题,然后在重新启动进程后,一切正常。 另外请注意这个问题与我的代码无关,它与序列化和 RMI 更相关。

代码在这里:

// The colling class    
Class CallingClass {
    Public void createSubscription (){

        TopicImpl topicPublisher = null;

        try {
            TopicImpl sessionInter = (TopicImpl) Naming.lookup(url);

            if (sessionInter != null) {

                topicPublisher = sessionInter.createMap();   
            }

        } catch (Exception e) {
            Logger.error(e);
        }
    }

}


The colling interface
public interface TopicImpl extends Remote {

    TestImpl createMap() throws RemoteException ;

}

// Concrete class for calling interface
public class TopicImplConcrete implements TopicImpl {

String name = "abc";

// this map is give some value during class initialization
private ConcurrentHashMap<String, TestImplConcrete> concHashMap = new ConcurrentHashMap<String, TestImplConcrete>();

    public TopicPublisher createMap() {
        TestImpl refOfHere = getMethodHere(name);
        return refOfHere;
        }

    public TestImplConcrete getMethodHere(String name) {
        if (name != null) {
            TestImplConcrete ref = concHashMap.get(name);
            if (ref != null)
                return ref;
            synchronized (this) {
                ref = concHashMap.get(name);
                if (ref != null)
                    return ref;
                ref = new TestImplConcrete(name);
                concHashMap.put(name, ref);
                try {
                    if (!ref.isExported()) {
                        UnicastRemoteObject.exportObject(ref);
                        ref.setExported(true);
                    }
                } catch (RemoteException e) {
                    log.error("Remote Exception", e);
                }
            }
            return ref;
        }
        return null;
    }
}

// The interface being sent over..
public interface TestImpl extends Remote {
    public TestImpl getMethod1()  throws RemoteException;
    public void method2()  throws RemoteException;
}

// concrete class for the interface being sent over.
public class TestImplConcrete implements TestImpl {
 private boolean isExportedBoolean;

 public boolean isExported() {
        return isExportedBoolean;
    }

    public void setExported(boolean isExportedBoolean) {
        this.isExportedBoolean = isExportedBoolean;
    }

    public TestImpl getMethod1() {
    // do something
    }

    public void method2() {
    // do something
    }
}

请注意:代码已经过编辑,仅提供相关信息。如果需要更多信息,请告诉我。上面粘贴的相同代码已经运行了好几年了。但这一次它显示 NotSerializableException

【问题讨论】:

  • "所有对象要么被正确序列化,要么被导出到需要的地方。"例外不同意你。在调用 createPublisher() 时,com.company.server.testImpl 既不是 Serializable 也不是导出的。
  • isPublisherExported() 测试毫无意义,关联的状态以及 getter 和 setter 也是如此。此时对象是全新的。不可能是出口的。不要测试永远不会是假的东西。更好的是,让对象扩展 UnicastRemoteObject 以便它在构造时导出。

标签: java rmi unmarshalling notserializableexception


【解决方案1】:

testImpl 不需要可序列化,但如果不是,则它确实需要在通过 RMI 传递或返回时已导出。

【讨论】:

  • 感谢您的回复。我看到返回语句确实返回了 testImpl。是否有可能 testImpl 的对象没有正确创建,因此返回了错误的引用导致错误?
  • 只是调查我已经给出的答案,而不是沉迷于疯狂的猜测。确保已导出。
  • 可能我完全糊涂了,或者我很笨。我检查并重新检查了代码,但那里似乎一切都很好。此外,代码每次都有效,但仅针对这一场合。
  • 那是什么代码?您的问题中没有发布任何内容。
  • 代码贴在原帖中。
猜你喜欢
  • 1970-01-01
  • 2016-10-17
  • 2018-06-02
  • 2017-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多