2011-04-26 58 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倍)。