【问题标题】:rmi java.lang.ClassNotFoundException: testrmi2.fileserverimpl_Stubrmi java.lang.ClassNotFoundException: testrmi2.fileserverimpl_Stub
【发布时间】:2021-08-03 00:21:02
【问题描述】:

我正在编写一个简单的 rmi 应用程序,但我遇到了问题。

如果我在同一目录中运行注册表,它可以工作;但是如果我更改了运行注册表的目录,它不会。

注册表通常可以在其他主机上工作,但只有更改目录才能停止其功能。

我正在解决这个问题 3 天没有解决方案,我还更改了代码库参数的所有可能配置,但没有。

我用目录描述情况和代码:

文件服务器.java:

`package testrmi2;
import java.rmi.*;

public interface fileserver extends Remote  {
 public void scrivifile(String nomefile, String arg) throws  RemoteException;
}

` fileserverimpl.java:

    package testrmi2;

import java.io.*;
import java.rmi.*;
import java.rmi.server.*;

public class fileserverimpl extends UnicastRemoteObject implements fileserver{
  public fileserverimpl() throws RemoteException {
    super();
  }
  public void scrivifile(String nomefile, String arg) throws RemoteException {
    try {
      FileWriter myfile = new FileWriter(nomefile);
      myfile.write(arg);
      myfile.close(); }
    catch (Exception e) {System.out.println(e);}
  }
  public static void main (String arg[]) {
    try {
       fileserverimpl s = new fileserverimpl();
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new RMISecurityManager());
        }
        String codebase = System.getProperty("classpath");
        System.out.println("Trying to access code base: " + codebase+"\n\nuse is "+System.getProperty("useCodebaseOnly"));
       Naming.rebind("//127.0.0.1:2005/fileserverimpl", s);
       System.out.println("Server attivato.");
} catch (Exception e) {System.out.println("errore inizializzazione server\n\n"+e.getMessage()+"\n\n\n");

}}}

client.java:

    package testrmi2;

import java.rmi.*;
import java.io.*;

public class client {
  public static void main (String arg[]) {
    fileserver myserver;
    String nomefile=" ";
    String testo=" ";
    System.out.println("Scrivi il nome del file");
    nomefile=ReadString();
    System.out.println("Scrivi il testo");
    testo=ReadString();
    try {
       myserver = (fileserver)   Naming.lookup("//127.0.0.1:2005/fileserverimpl");
        myserver.scrivifile(nomefile, testo);
      } catch (Exception e) {System.out.println(e);}
    }

   public static String ReadString() {
      BufferedReader stdIn =new BufferedReader(new InputStreamReader(System.in));
      String s=" ";
     try{
       s=stdIn.readLine();
      }
       catch(IOException e) {System.out.println(e.getMessage()); }
    return s;
   }
}

政策文件是:

grant {
        // Allow everything for now
        permission java.security.AllPermission;
}; 

所有这些文件都在目录中:

/Users/franco/Desktop/prova

要编译它,我进入 /Users/franco/Desktop/prova 目录并在终端中执行:

javac -cp . -d . *.java
rmic rmic testrmi2.fileserverimpl
jar cvf testrmi2.jar testrmi2/fileserver.class testrmi2/fileserverimpl_Stub.class

在另一个终端使用以下命令但在另一个目录中运行注册表后:

export classpath=""
rmiregistry 2005 &

最后,我会在 /Users/franco/Desktop/prova 目录中运行与终端一起使用的filesereveimpl.class并写入:

java -classpath /Users/franco/Desktop/prova/ -Djava.rmi.server.codebase=file:/Users/franco/Desktop/prova/testrmi2.jar  -Djava.security.policy=testrmi2/policy testrmi2.fileserverimpl &

但结果是:

    Trying to access code base: null

use is null
errore inizializzazione server

RemoteException occurred in server thread; nested exception is: 
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: testrmi2.fileserverimpl_Stub

我还尝试在本地网络服务器 xampp 上公开他的 jar 并尝试使用以下内容运行:

java -classpath .  -Djava.rmi.server.codebase=http://127.0.0.1/testrmi2/  -Djava.security.policy=testrmi2/policy  testrmi2.fileserverimpl &

或与:

java -classpath .  -Djava.rmi.server.codebase=http://127.0.0.1/testrmi2.jar  -Djava.security.policy=testrmi2/policy  testrmi2.fileserverimpl &

但我有相同的结果。

【问题讨论】:

    标签: java rmi


    【解决方案1】:

    在执行rmregistry之前尝试设置classpath var:

    export classpath="/Users/franco/Desktop/prova/"
    rmiregistry 2005 &
    

    【讨论】:

      【解决方案2】:

      有三种情况。

      1. 在导出/构造远程对象时,您在服务器中遇到了该异常。解决方案:运行 rmic 生成存根。
      2. 绑定/重新绑定时,您在服务器中获取了它。解决方案:让 stub 类对 Registry 的 CLASSPATH 可用,或者通过 LocateRegistry.createRegistry() 在服务器 JVM 中运行 Registry。
      3. 您在客户端的lookup() 中获得了它。解决方案:使存根类可用于客户端的 CLASSPATH。

      这些也适用于远程接口本身,以及它所依赖的任何应用程序类,以此类推,直到关闭。

      所有三个存根的解决方案:采取 Javadoc 序言中概述的 UnicastRemoteObject 的措施,因此您根本不需要存根。

      【讨论】:

      • 当我在服务器中进行绑定时,问题就开始了。我不知道为什么我必须从注册表中获取存根类。我会用代码库来做这件事,因为我认为它也可以在另一台主机上工作。在这种情况下,考虑到不同的机器和动态类路径的变化,如何在注册表类路径中动态插入我的存根?可以打印代码库或者打印在代码上看java是否读取了我的参数????
      • 您将存根绑定到注册表中,因此您必须使该类对注册表可用。如果您正在使用代码库功能,则不需要在注册表中提供该类:这就是代码库功能的用途。但是代码库必须是注册表和客户端可以理解的东西,并且 file: URL 不能满足这一点,除非它们引用从另一个主机查看的共享文件夹。大多数人使用 HTTP 代码库。
      猜你喜欢
      • 2012-05-30
      • 1970-01-01
      • 1970-01-01
      • 2012-06-21
      • 2023-04-09
      • 2013-11-05
      • 1970-01-01
      • 2021-05-09
      相关资源
      最近更新 更多