2013-03-22 41 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的序言。