2011-04-26 57 views
0

我花了近五個小時試圖解決這個問題,但沒有用。我創建了一個使用RMI的應用程序。它編譯好,但我不能讓它運行。 我所有的類文件都在C:\ Users \ Benji \ Desktop \ ass2 \ build(簡稱爲「賦值」;沒有任何髒東西)。所有源文件都在C:\ Users \ Benji \ Desktop \ ass2 \ src中。 我已經把所有東西放在一個包中,以使事情更容易理解(並且改變了源代碼中的導入語句以反映這一點)。RMI - 在運行時獲取ClassNotFoundException

我已經把一個批處理文件放在C:\ Users \ Benji \ Desktop \ ass2 \中。其中包含執行聲明:

java -classpath ./build -Djava.rmi.server.codebase=file:/C:/Users/Benji/Desktop/ass2/build -Djava.security.policy=broker.policy BrokerReception Broker 16890 

(該程序需要兩個參數「Broker」和「16890」)。

文件broker.policy也位於C:\ Users \ Benji \ Desktop \ ass2 \中。它的內容是:

grant 
{ 
    permission java.security.AllPermission; 
}; 

(是的,我意識到這不是一個好的安全策略,我會在稍後的工作)。

實際上有三個主類,一個用於客戶端,一個用於代理(用於客戶端的中介)和一個服務器。我正在嘗試啓動經紀商。規範經紀界面如下:

import java.io.FileNotFoundException; 
import java.rmi.Remote; 
import java.rmi.RemoteException; 
import java.util.ArrayList; 

public interface Broker extends Remote 
{ 
    public boolean getAvailability(int startDate, int endDate) throws FileNotFoundException, RemoteException; 

    public ArrayList<CityInfo> getCities() throws FileNotFoundException, RemoteException; 

    public ArrayList<HotelInfo> getCityHotels(int cityNumber) throws FileNotFoundException, RemoteException; 

    public int getHotelRoomRate(int hotelNumber) throws FileNotFoundException, RemoteException; 

    public boolean makeBooking(String firstName, String lastName, String contact, String creditCardNo) throws FileNotFoundException, RemoteException; 
} 

而實現類:

import java.io.FileNotFoundException; 
import java.util.ArrayList; 

public class BrokerClientLiaison implements Broker 
{ 
    private BrokerDatabase directory; 
    private BrokerHotelsLiaison liaison; 

    public BrokerClientLiaison(BrokerDatabase directory, int activeHotelNumber) 
    { 
     this.liaison = new BrokerHotelsLiaison(activeHotelNumber); 
     this.directory = directory; 
    } 

    public boolean getAvailability(int startDate, int endDate) throws FileNotFoundException 
    { 
     return liaison.getAvailability(startDate, endDate); 
    } 

    public ArrayList<CityInfo> getCities() throws FileNotFoundException 
    { 
     return directory.getCities(); 
    } 

    public ArrayList<HotelInfo> getCityHotels(int cityNumber) throws FileNotFoundException 
    { 
     return directory.getCityHotels(cityNumber); 
    } 

    public int getHotelRoomRate(int hotelNumber) throws FileNotFoundException 
    { 
     return liaison.getHotelRoomRate(hotelNumber); 
    } 

    public boolean makeBooking(String firstName, String lastName, String contact, String creditCardNo) throws FileNotFoundException 
    { 
     return liaison.makeBooking(firstName, lastName, contact, creditCardNo); 
    } 
} 

最後,主類開始執行類:

import java.io.FileNotFoundException; 
import java.rmi.RemoteException; 
import java.rmi.registry.LocateRegistry; 
import java.rmi.registry.Registry; 
import java.rmi.server.UnicastRemoteObject; 
import java.sql.SQLException; 

public class BrokerReception 
{ 
    public static void main(String[] args) 
    { 
     System.out.println("Args are:"); 
     for(String arg : args) 
     { 
      System.out.println(arg); 
     } 
     System.out.println(); 

     try 
     { 
      BrokerDatabase directory = new BrokerDatabase(); 
      directory.connect(args[0]); 

      int activeHotelNumber = Integer.parseInt(args[1]); 
      if(directory.checkActiveHotelExists(activeHotelNumber)) 
      { 
       BrokerClientLiaison liaison = new BrokerClientLiaison(directory, activeHotelNumber); 
       Broker liaisonStub = (Broker) UnicastRemoteObject.exportObject(liaison, 0); 
       Registry registry = LocateRegistry.getRegistry(); 
       registry.rebind(Protocol.BROKER_INTERFACE_NAME, liaisonStub); 
      } 
      else 
      { 
       throw new FileNotFoundException(); 
      } 
     } 
     catch(ArrayIndexOutOfBoundsException aioobe) 
     { 
      System.err.println("Args required:"); 
      System.err.println("1. Name of database file"); 
      System.err.println("2. Number of active hotel"); 
      System.exit(1); 
     } 
     catch(ClassNotFoundException cnfe) 
     { 
      System.err.println("Couldn't load database driver"); 
      System.exit(2); 
     } 
     catch(SQLException sqle) 
     { 
      System.err.println("Couldn't establish connection to database"); 
      System.err.println("Check that the database has been properly registerd,"); 
      System.err.println("and that you provided the correct name"); 
      System.exit(3); 
     } 
     catch(NumberFormatException nfe) 
     { 
      System.err.println("Second argument must be an integer"); 
      System.exit(4); 
     } 
     catch(FileNotFoundException fnfe) 
     { 
      System.err.println("The database contains no entries with that hotel number"); 
      System.exit(5); 
     } 
     catch(RemoteException re) 
     { 
      System.err.println("Unable to bind as " + Protocol.BROKER_INTERFACE_NAME); 
      re.printStackTrace(); 
      System.exit(6); 
     } 
    } 
} 

「目錄」在上面的代碼中是一個訪問數據庫的類。

我不知道我需要提供哪些其他信息。有人可以告訴我我做錯了什麼嗎? 順便提一句,我回去做了Oracle的RMI教程http://download.oracle.com/javase/1.5.0/docs/guide/rmi/hello/hello-world.html,看我能否弄清楚什麼是錯的。本教程沒有提到代碼庫或安全策略,但提供了編譯和執行的所有代碼和準確說明。我按照這些說明來寫信,但即使這樣也行不通!

堆棧跟蹤:

java.rmi.ServerException: RemoteException occurred in server thread; nested exce 
ption is: 
     java.rmi.UnmarshalException: error unmarshalling arguments; nested excep 
tion is: 
     java.lang.ClassNotFoundException: Broker 
     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:5 
35) 
     at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTranspor 
t.java:790) 
     at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport 
.java:649) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExec 
utor.java:886) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor 
.java:908) 
     at java.lang.Thread.run(Thread.java:662) 
     at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Stream 
RemoteCall.java:255) 
     at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java: 
233) 
     at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:359) 
     at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source) 
     at BrokerReception.main(BrokerReception.java:32) 
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested ex 
ception is: 
     java.lang.ClassNotFoundException: Broker 
     at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source) 
     at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:386 
) 
     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:5 
35) 
     at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTranspor 
t.java:790) 
     at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport 
.java:649) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExec 
utor.java:886) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor 
.java:908) 
     at java.lang.Thread.run(Thread.java:662) 
Caused by: java.lang.ClassNotFoundException: Broker 
     at java.net.URLClassLoader$1.run(URLClassLoader.java:202) 
     at java.security.AccessController.doPrivileged(Native Method) 
     at java.net.URLClassLoader.findClass(URLClassLoader.java:190) 
     at java.lang.ClassLoader.loadClass(ClassLoader.java:307) 
     at java.lang.ClassLoader.loadClass(ClassLoader.java:248) 
     at java.lang.Class.forName0(Native Method) 
     at java.lang.Class.forName(Class.java:247) 
     at sun.rmi.server.LoaderHandler.loadProxyInterfaces(LoaderHandler.java:7 
11) 
     at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:655) 
     at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:592) 
     at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:6 
28) 
     at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:294 
) 
     at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStrea 
m.java:238) 
     at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1530) 
     at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1492) 
     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1 
731) 
     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328) 
     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350) 
     ... 12 more 
+3

堆棧跟蹤會有幫助 - 找不到哪個類。嘗試在try..catch處理程序中從'cnfe'捕獲真正的類名 - 也許,它不是數據庫驅動類... – 2011-04-26 09:38:47

+0

...以及當你得到它時你在做什麼。有3種不同的情況。 – EJP 2011-04-26 11:20:27

+0

對不起,忘了堆棧跟蹤。我已經離開了幾天:/。未找到的類似乎是代理界面。 另外,最奇怪的事情:我已經完成了第二個教程,它可以在http://download.oracle找到。com/javase/tutorial/rmi/index.html。 – Swiftslide 2011-04-28 22:49:47

回答

1

如果您運行的註冊表作爲第二過程中,需要訪問你的遠程類。最簡單的方法是在啓動註冊表時將相應的類路徑參數添加到命令行中。

如果您嘗試使用遠程類加載,我相信您需要在您的應用程序中安裝rmi安全管理器,無論是在命令行還是主要方法中。 (個人而言,分發課程通常適用於99%的情況,而且容易獲得100倍)。