我花了差不多五个小时试图解决这个问题,但无济于事。我创建了一个使用RMI的应用程序。编译很好,但我不能让它运行。 我的所有类文件都在C:\ Users \ Benji \ Desktop \ ass2 \ build中(“赋值”的缩写;没有任何脏)。所有源文件都在C:\ Users \ Benji \ Desktop \ ass2 \ src中。 我已将所有内容放在一个包中以使事情更易于理解(并更改源中的import语句以反映这一点)。
我已将批处理文件放在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
(程序需要两个“经纪人”和“16890”)。
文件broker.policy也位于C:\ Users \ Benji \ Desktop \ ass2 \中。其内容如下:
grant
{
permission java.security.AllPermission;
};
(是的,我意识到这不是一个好的安全政策。我稍后会讨论这个问题。)
实际上有三个Main类,一个用于客户端,一个用于代理(客户端的中介)和服务器。我正在尝试启动经纪人。 Broker接口的代码如下:
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);
}
}
}
上述代码中的“目录”是访问数据库的类。
我不知道我需要提供什么其他信息。谁能告诉我我做错了什么? 顺便说一句,我回去并在http://download.oracle.com/javase/1.5.0/docs/guide/rmi/hello/hello-world.html做了Oracle的RMI教程,看看我是否能弄明白什么是错的。本教程未提及代码库或安全策略,但提供了编译和执行的所有代码和精确指令。我按照这些说明写了这封信,但即使这样也行不通!
堆栈追踪:
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
答案 0 :(得分:1)
如果您将注册表作为第二个进程运行,则需要访问您的远程类。最简单的方法是在启动注册表时向命令行添加适当的类路径参数。
如果您尝试使用远程类加载,我相信您需要在命令行或主方法中在应用程序中设置rmi安全管理器。 (就个人而言,分发课程通常适用于99%的情况,并且容易100倍正确)。