分享

JAVA NoClassDefFoundError

 kidden2007 2012-05-03
2012.5.3
进行RMI基础的实验,步骤见本文后附。运行java RemServer.class,出现下图所示错误:
 
 
查询RemServer.java 代码为发现错误,网上搜索,有说路径问题、有说java版本问题,最后发现有 http://wolfdream./blog/1131558 一文中提到不应加.class,于是运行java RemServer,成功。

实验参考文章如下(红色为需要修改部分):

如何在Java中实现远程方法调用

经乾、郭镇、赵伟 2001-01-22 10:45:09

 

  一、Java中的远程方法调用

  远程方法调用(Remote Method Invocation, RMI)是Java1.1引入的分布式对象软件包,它的出现简化了在多台机器上的Java应用之间的通信。相比CORBARMI功能较弱且只能用于Java系统。

 

  二、实现一个简单的RMI

  要使用RMI,必须构造四个主要的类:远程对象的本地接口、RMI客户、远程对象实现和RMI服务器。RMI服务器生成远程对象实现的一个实例,并用一个特殊的URL注册它,RMI客户在远程服务器上查找对象,若找到就把它转换成本地接口类型,然后像一个本地对象一样使用它。下面是一个简单的RMI例子,远程对象只返回一个消息字符串。要使这个例子更有价值,我们需要做的就是完善远程对象实现类。

 

  1.远程对象的本地接口类(Rem.java

  该类仅仅是一个接口,而不是实现,RMI客户机可以直接使用它,RMI服务器必须通过一个远程对象来实现它,并用某个URL注册它的一个实例。

  import java.rmi.*;

 

  public interface Rem extends Remote { public String getMessage() throws RemoteException;}

 

  本地接口(Rem)必须是公共的,否则客户机在加载一个实现该接口的远程对象时就会出错。此外,它还必须从java.rmi.Remote继承而来,接口中的每一个方法都必须抛出远程异常java.rmi.RemoteException

 

  2.RMI客户类(RemClient.java

 

  RMI客户使用Naming.lookup在指定的远程主机上查找对象,若找到就把它转换成本地接口Rem类型,然后像一个本地对象一样使用它。与CORBA不同之处在于RMI客户必须知道提供远程服务主机的URL,这个URL可以通过rmi://host/pathrmi://host:port/path来指定,如果省略端口号,就使用1099Naming.lookup可能产生三个异常:RemoteExceptionNotBoundExceptionMalformedURLException,三个寻常都需要捕获。RemoteExceptionNamingNotBoundExceptionjava.rmi.*中定义,MalformedURLExceptionjava.net.*中定义。另外,客户机将向远程对象传递串行化对象Serializable,所以还应在程序中输入java.io.*

 

  import java.rmi.*;

 

  import java.net.*;

 

  import java.io.*;

 

  public class RemClient {

 

  public static void main(String[] args) {

 

  try {

 

  String host = (args.length > 0) ? args[0] : "localhost"; //从命令行读取远程主机名

 

  //通过URL在远程主机上查找对象,并把它转化为本地接口Rem类型

 

  Rem remObject=(Rem)Naming.lookup("rmi://" + host + "/Rem");

 

  System.out.println(remObject.getMessage()); //调用远程对象的方法

 

  } catch(RemoteException re) {System.out.println("RemoteException: " + re);

 

  } catch(NotBoundException nbe) {System.out.println("NotBoundException: " + nbe);

 

  } catch(MalformedURLException mfe){System.out.println("MalformedURLException:"+ mfe);

 

  }}}

 

  3.远程对象实现类(RemImpl.java

 

  这个类真正实现RMI客户调用的远程对象,它必须从UnicastRemoteObject继承,其构造函数应抛出RemoteException异常。

 

  import java.rmi.*;

 

  import java.rmi.server.UnicastRemoteObject;

 

  public class RemImpl extends UnicastRemoteObject implements Rem {

 

   public RemImpl() throws RemoteException {} //构造函数抛出RemoteException异常

 

   public String getMessage() throws RemoteException {

 

   return("Here is a remote message."); }} //RMI客户返回一个消息串

 

  4.RMI服务器类(RemServer.java

 

  该类创建远程对象实现RemImpl的一个实例,然后用一个特定的URL来注册它,所谓注册就是通过Naming.bindNaming.rebind来将RemImpl实例绑定到URL上。

 

  import java.rmi.*;

 

  import java.net.*;

 

  public class RemServer {

 

  public static void main(String[] args) {

 

  try {

 

  RemImpl localObject = new RemImpl(); //生成远程对象实现的一个实例

 

  Naming.rebind("rmi:///Rem", localObject); //将远程对象实例绑定到rmi:///Rem

 

  }catch(RemoteException re){System.out.println("RemoteException:"+re);

 

  }catch(MalformedURLException mfe) {System.out.println("MalformedURLException: "+mfe);

 

  }}}

 

  三、编译和运行

  1. 编译RMI客户和服务器,这将自动编译远程对象的本地接口和远程对象实现

 

  javac RemClient.java //自动编译远程对象的本地接口Rem.java

 

  javac RemServer.java //自动编译远程对象实现RemImpl.java

 

  2. 生成客户承接模块和服务器框架

 

  rmic RemImpl

 

  这将构造RemImpl_Stub.classRemImpl_Skeleton.class。请将Rem.classRemClient.classRemImpl_Stub.class拷贝到RMI客户机,将Rem.classRemImpl.class RemServer.classRemImpl_Skeleton.class拷贝到RMI服务器。

 

  3. 启动RMI注册

 

  start rmiregistry

 

  //在服务器上执行。不论有多少个远程对象,本操作只需做一次

 

  4. 运行

 

  java RemServer.class

 

  //启动RMI服务器(在服务器上执行)

 

  java RemClient.class

 

//启动RMI客户,将输出“Here is a remote message.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多