2013-03-22 43 views
0

我决定编写RMI(从书中)也从书中取得代码。我用rmic创建了存根,并启动了rmiregistry,但是当我决定编写java Start Server时,我遇到了问题,其实这里是我遇到的问题: java -classpath D:\ RMI AddServer 异常:java.rmi。 ServerException:在服务器线程中发生RemoteException; 意外的异常是: java.rmi.UnmarshalException:错误解组参数;嵌套excep 重刑是: 抛出java.lang.ClassNotFoundException:AddServerImpl_Stub 请我需要帮助,我失去了很多时间,因为这:(Java RMI ClassNotFound例外

AddServerIntf.java

package rmi.app; 
import java.rmi.*; 
public interface AddServerIntf extends Remote { 
    double add(double d1,double d2) throws RemoteException;} 

AddServerImpl

package rmi.app; 
import java.rmi.*; 
import java.rmi.server.*; 
public class AddServerImpl extends UnicastRemoteObject implements AddServerIntf { 

public AddServerImpl() throws RemoteException {} 

public double add(double d1, double d2) throws RemoteException { 
     return d1+d2; 
    } 

} 

AddSer版本

package rmi.app; 
    import java.net.*; 
    import java.rmi.*; 
    public class AddServer { 
public static void main(String[] args) { 

    try { 

    AddServerImpl addServerImpl = new AddServerImpl(); 
    Naming.rebind("AddServer", addServerImpl);  
    } 
    catch (Exception e){ 
     System.out.println("Exception:"+e); 
    } 

} 

    } 

了addClient

package rmi.app; 
    import java.rmi.Naming; 
    public class AddClient { 
public static void main(String[] args) { 

    try{ 
     String addServerURL= "rmi://"+args[0]+ "/AddServer"; 
     AddServerIntf addServer =(AddServerIntf)Naming.lookup(addServerURL); 
     System.out.println("The first number is:"+args[1]); 
     double d1= Double.valueOf(args[1]).doubleValue(); 
     System.out.println("The second number is:"+args[2]); 
     double d2= Double.valueOf(args[2]).doubleValue(); 
     System.out.println("the sum is:"+ addServer.add(d1,d2)); 

    } 
    catch(Exception e){ 
     System.out.println("Exception : "+ e); 
    } 

} 

    } 
+0

您正在使用哪个版本的java? – wmorrison365 2013-03-22 17:48:20

+0

看看我的回答,你写的时候可能会把你的代码放在问题中。你可能太接近了。 – 2013-03-22 17:56:44

回答

1

简短的回答:注册表需要有在其类路径的存根。

龙答:从过去10年中,其使用RMIC,因为你有没有需要做的一切,对于一个长期时间内找到一个RMI教程。

+0

这很难,我花了近2周的时间研究它,而且那里的材料非常不完整。 :-) – 2013-03-22 17:58:17

+0

@PauloPedroso - “java rmi tutorial”的前2名都是最新且合理完整的http://docs.oracle.com/javase/tutorial/rmi/index.html和http:// docs .oracle.com/javase/6/docs/technotes/guides/rmi/hello/hello-world.html(均不使用rmic)。 – jtahlborn 2013-03-22 18:26:50

+0

@PauloPedroso - 虽然我同意你的回答,你不应该使用SecurityManager和政策的东西,这只是混乱的主要教程。 – jtahlborn 2013-03-22 18:28:40

2

我正在编写一个Java RMI应用程序,并且在能够使它工作之前经历了很多。经过大量的研究和尝试和错误,我得到了这个“配方”:

  1. 不要安装SecurityManager;
  2. 请勿使用策略文件;
  3. 确保您从一个虚拟机迁移到另一个虚拟机的类在 客户端和服务器类路径(或在同一个jar/war中)。
  4. 如果您使用休眠模式访问数据库,请将罐子放在 客户端中。休眠“改变”原来的类和客户端 将需要这反序列化它;
  5. 如果您同时在服务器端使用Spring,你可能包括弹簧ORM弹簧数据的JPA罐子在客户端,如果您遇到ClassNotFoundException的后面JpaObjectRetrievalFailureException;
  6. 我没有在罐子外面运行任何东西(根本没有rmi服务);
  7. 我没有创建存根,因为我正在使用Java 6。

我的服务器,纯粹是这样:

try { 
     try { 
      LocateRegistry.createRegistry(SERVER_PORT); 
     } catch (RemoteException e) { 
      LocateRegistry.getRegistry(SERVER_PORT); 
      e.printStackTrace(); 
     } 
     System.setProperty("java.rmi.server.hostname", SERVER_HOST); 
     connectionRequestHandler = new ConnectionRequestHandlerImpl(); 
     dataRequestHandler = new DataRequestHandlerImpl(); 
     String rmiUrl = "rmi://" + SERVER_HOST + ":" + SERVER_PORT + "/"; 
     Naming.rebind(rmiUrl + "ConnectionRequestHandler", connectionRequestHandler); 
     Naming.rebind(rmiUrl + "DataRequestHandler", dataRequestHandler); 
    } catch (RemoteException e1) { 
     e1.printStackTrace(); 
    } catch (MalformedURLException e) { 
     e.printStackTrace(); 
    } 
} 

然后在客户端我做的:

String rmiUrl = "rmi://" + SERVER_HOST + ":" + SERVER_PORT + "/"; 
    try { 
     connectionRequestHandler = (ConnectionRequestHandler)Naming.lookup(rmiUrl + "ConnectionRequestHandler"); 
     dataRequestHandler = (DataRequestHandler)Naming.lookup(rmiUrl + "DataRequestHandler"); 
    } catch (MalformedURLException e) { 
     throw new RmiServicesDownException(e.getMessage()); 
    } catch (RemoteException e) { 
     throw new RmiServicesDownException(e.getMessage()); 
    } catch (NotBoundException e) { 
     throw new RmiServicesDownException(e.getMessage()); 
    } catch (Exception e){ 
     e.printStackTrace(); 
     return; 
    } 

这是它是如何为我工作。与第一次设置相比,您可能遇到的任何其他问题都很容易解决。

+0

我会添加到该列表“不要使用代码库功能”:至少不是一开始。这是一个*部署*选项:不要让它搞砸你的最初发展。如果您打算使用它,请记住它确实要求安装管理程序和策略文件,但您可以稍后再解决这些问题。 – EJP 2013-03-22 22:55:23

0

更改AddServerImpl构造函数以调用super(0)。那么你甚至不需要生成一个存根,更不用说部署它了。请参阅UnicastRemoteObject的Javadoc的序言。