java RMI NotSerializableException 虽然它是一个远程对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11049810/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
RMI NotSerializableException although it's a remote object
提问by Graslandpinguin
I'm writing a small RMI based Chat application.
我正在编写一个基于 RMI 的小型聊天应用程序。
The idea is: the Client registers himself on the Server, and everytime the server receives a message from a client, he pushes this message to all other clients.
思路是:Client在Server上注册自己,每次Server收到一个客户端的消息,他就把这条消息推送给所有其他的客户端。
But I receive a NotSerializableException although, the object, I'm passing as a method parameter implements the Remote interface.
但是我收到一个 NotSerializableException 虽然,我作为方法参数传递的对象实现了远程接口。
Here is some code:
(The problematic part is the this
parameter in this.chatServ.registriereClient(this);
(ClientChat Implementation))
这是一些代码:(有问题的部分是(ClientChat Implementation)中的this
参数this.chatServ.registriereClient(this);
)
The (ClientChat)interface:
(ClientChat) 界面:
public interface ChatClient extends Remote
{
}
(ClientChat)Implementation:
(ClientChat)实现:
public class ChatClientImpl implements ChatClient
{
ChatServer chatServ;
String clientName;
public ChatClientImpl(String clientName, ChatServer chatServ) {
this.chatServ = chatServ;
this.clientName = clientName;
try {
this.chatServ.registriereClient(this);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
(ServerChat) Interface
(ServerChat) 界面
public interface ChatServer extends Remote
{
void registriereClient(ChatClient client) throws RemoteException;
}
(ServerChat) Implementation
(ServerChat) 实现
public class LobbyChatServerImpl implements ChatServer
{
ArrayList<ChatClient> clientListe = null;
@Override
public void registriereClient(ChatClient client) {
System.out.println("Client registriert");
this.clientListe.add(client);
}
}
Client:
客户:
public static void main(String[] args) {
ChatServer lobbyChatServer = null;
try {
Registry registry = LocateRegistry.getRegistry(Server.RMI_PORT);
lobbyChatServer = (ChatServer) registry.lookup("LobbyChatServer");
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
ChatClient lobbyChat = new ChatClientImpl(name, lobbyChatServer);
}
Server:
服务器:
public static void main(String[] args) {
try {
if (System.getSecurityManager() == null) {
System.setSecurityManager(new RMISecurityManager());
}
Registry registry = LocateRegistry.getRegistry(RMI_PORT);
ChatServer lobbyChatStub = (ChatServer)UnicastRemoteObject.exportObject(new LobbyChatServerImpl(), 0);
registry.bind("LobbyChatServer", lobbyChatStub);
} catch (RemoteException e) {
e.printStackTrace();
} catch (AlreadyBoundException e) {
e.printStackTrace();
}
}
Exception:
例外:
java.rmi.MarshalException: error marshalling arguments; nested exception is:
java.io.NotSerializableException: de.XX.Chat.ChatClientImpl
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:156)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:194)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:148)
at $Proxy0.registriereClient(Unknown Source)
at de.XX.Chat.ChatClientImpl.<init>(ChatClientImpl.java:19)
at de.XX.Client.main(Client.java:49)
Caused by: java.io.NotSerializableException: de.XX.Chat.ChatClientImpl
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1180)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
at sun.rmi.server.UnicastRef.marshalValue(UnicastRef.java:292)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:151)
... 5 more
As already said, I wonder why i get this kind of Exception, although ChatClientImpl is already Remote.
如前所述,我想知道为什么我会收到这种异常,尽管 ChatClientImpl 已经是远程的。
Hope you can help me:)
希望你能帮我:)
回答by user207421
Objects passed as parameters or results of remote methods must be either:
作为远程方法的参数或结果传递的对象必须是:
Serializable (or Externalizable), or
Exportedremote objects.
可序列化(或可外部化),或
导出的远程对象。
Yours is neither. However as it implements a Remote interface clearly you intended (2).
Objects that extend UnicastRemoteObject
are auto-exported on construction. Objects that don't must be exported explicitly, via UnicastRemoteObject.exportObject()
.
你的都不是。然而,因为它实现了一个远程接口,你很清楚(2)。扩展的对象UnicastRemoteObject
在构造时自动导出。不需要的对象必须显式导出,通过UnicastRemoteObject.exportObject()
.
回答by Peter Lawrey
What you can do is setup a callback object. This is one which extends UnicastRemoteObject and when you pass this it becomes a callback.
你可以做的是设置一个回调对象。这是一个扩展 UnicastRemoteObject 并且当你传递它时它变成一个回调。
http://www.cs.swan.ac.uk/~csneal/InternetComputing/RMIChat.html
http://www.cs.swan.ac.uk/~csneal/InternetComputing/RMIChat.html
Remoteis not Serializable. You can't pass a proxy object this way. Even if you made it Serializable it would send a copyof the object which would exist on the server. The copy of the object on the client would not be called.
远程不可序列化。您不能以这种方式传递代理对象。即使您将其设置为可序列化,它也会发送服务器上存在的对象的副本。不会调用客户端上的对象副本。
For your "server" to send messages to your "client" you have to create a service on the "client" to make it a server.
为了让您的“服务器”向您的“客户端”发送消息,您必须在“客户端”上创建一个服务以使其成为服务器。
You may find that using a messaging solution such as JMS is better suited to this take. A JMS server has topics which you can publish to and subscribe from. A simple JMS server to use is Active MQ.
您可能会发现使用诸如 JMS 之类的消息传递解决方案更适合这种情况。JMS 服务器具有您可以发布和订阅的主题。一个简单的 JMS 服务器是 Active MQ。
回答by leon
Looks like you might have forgotten to 'extends UnicastRemoteObject' on the interface implementations:
看起来您可能忘记在接口实现上“扩展 UnicastRemoteObject”:
public class ChatClientImpl extends UnicastRemoteObject implements ChatClient{
}
and
和
public class LobbyChatServerImpl extends UnicastRemoteObject implements ChatServer{
}