2011-08-24 66 views
0

我已經繼承了一些Java RMI客戶機/服務器代碼,雖然它在一臺機器上運行良好,但我一直無法獲得它在我的開發環境中運行。Java RMI ServerException - java.lang.ClassNotFoundException:org.prog.rmi.RmiServer_Stub

問題是,當我使用以下java.exe -Djava.security.policy=conf\server.policy -SRC;. -Djava.library.path=. org.prog.rmi.RmiServer

我碰到下面的錯誤運行服務器:

java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
java.lang.ClassNotFoundException: org.prog.rmi.RmiServer_Stub (no security manager: RMI class loader disabled) 
    at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:396) 
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:250) 
    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) 
    ... 

server.policy文件

grant { 
    permission java.security.AllPermission; 
}; 

我的Java代碼:

 package org.prog.rmi; 

     import java.rmi.Naming; 
     import java.rmi.RemoteException; 
     import java.rmi.RMISecurityManager; 
     import java.rmi.server.UnicastRemoteObject; 
     import java.rmi.registry.*; 

     public class RmiServer extends UnicastRemoteObject 
      implements RmiServerIntf { 

     private BatchApi bapi; 
     private String iniFileLocation; 
     private String layoutOption; 
     private int addressCount = 0; 
     private RefInt apiHandle = new RefInt(); 


     public RmiServer(String iniFileLocation,String layoutOption) throws RemoteException 
     { super(); 
      this.iniFileLocation = iniFileLocation; 
      this.layoutOption = layoutOption; 
      initAPI(); 
      startupAPI(); 
      openAPI();  
     } 

     public static void main(String args[]) 
     { 
      System.out.println("RMI server started"); 

      // Create and install a security manager 
      if (System.getSecurityManager() == null) 
      { 
       System.setSecurityManager(new RMISecurityManager()); 
       System.out.println("Security manager installed."); 
      } 
      else 
       System.out.println("Security manager already exists."); 

      try //special exception handler for registry creation 
      { 
       LocateRegistry.createRegistry(1099); 
       System.out.println("java RMI registry created."); 
      } 
      catch (RemoteException e) 
      { 
       //do nothing, error means registry already exists 
       System.out.println("java RMI registry already exists."); 
      } 

      try 
      { 
       //Instantiate RmiServer 
       for (String arg: args){ 
        System.out.println(arg); 
       } 

       RmiServer obj = new RmiServer(args[0],args[1]); 

       // Bind this object instance to the name "RmiServer" 
       Naming.rebind("//127.0.0.1/RmiServer", obj); 
       System.out.println("PeerServer bound in registry"); 

      } 
      catch (Exception e) 
      { 
       System.err.println("RMI server exception:"); 
       e.printStackTrace(); 
      } 
     }  
} 

我已經看到了有關的java.rmi.server.codebase解決方案,但沒有任何運氣設置此任

+0

不應該將服務器綁定到「rmi:// localhost:1099/RmiServer」嗎?您的網址似乎沒有正確書寫。我不確定這是問題的原因,但修復這將是一個好的開始。 –

+0

這聽起來很棘手,我自己繼承了一些RMI代碼,但運行它並沒有太多麻煩。我們做的一件事就是將我們編譯的jar與客戶端和服務器都打包在一起。至少可以確保所有相同的內部類定義可用。 – gnomed

+0

另外,在開發環境之外運行代碼時,您確定要使用JDK 1.5或更高版本嗎?我相信自動生成代理的功能在JDK 1.5中提供,並且僅用於擴展UnicastRemoteObject的服務器,否則您將強制rmic您的服務器並自行生成存根。 –

回答

0

經過一番深入調查並按照RMI教程就顯得有在端口1099

的RMI註冊服務器的一個問題。當我盯着另一個端口(例如2005)的RMI註冊服務器,改變了這些線路代碼

LocateRegistry.createRegistry(2005); 

Naming.rebind("//127.0.0.1:2055/RmiServer", obj); 

這成功地運行,沒有錯誤,我的客戶是能夠連接。

我希望這個答案可以幫助其他人解決這個錯誤。讓我知道是否有人需要更詳細的信息。

+2

只是改變端口號不會解決這個問題。我懷疑在1099上創建它時默默地失敗了,因爲已經有另一個註冊表在其類路徑中運行時沒有存根,並且因爲異常被抑制或忽略。 – EJP

0

您還沒有再生存根與RMIC,或註冊表不通過它的類路徑訪問它。

+0

嗨EJP,你能提供一些額外的解釋嗎?當RMI服務器程序移動到另一臺機器時,是否需要重新生成存根文件 - 我可不只是將存根文件複製到另一臺機器上?我剛剛嘗試使用代碼rmic org.prog.rmi.RmiServer重新生成它,這似乎沒有什麼區別。我不確定你的意思是「註冊表無法通過它的類路徑訪問它」 - 我需要在這裏做什麼? – Loftx

+0

@Loftx這是一個編譯步驟,它不依賴於哪臺機器。你可以複製它。您需要通過LocateRegistry在服務器JVM(推薦)中啓動註冊表,或者使用-J-Dclasspath啓動* rmiregistry * =需要任何JAR文件。 – EJP