首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RMI:将两个远程对象绑定到同一注册表时引发的ClassNotFoundException

RMI:将两个远程对象绑定到同一注册表时引发的ClassNotFoundException
EN

Stack Overflow用户
提问于 2014-03-06 18:10:20
回答 1查看 369关注 0票数 0

我有两个远程对象,我正试图将它们绑定到同一个RMI注册表。下面是我的项目结构:

我的第一个类(RemoteServer1.java)

代码语言:javascript
复制
package com.abc.rmi;

import java.rmi.AccessException;
import java.rmi.AlreadyBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import org.apache.log4j.Logger;


public class RemoteServer1 implements IServer1Interface{

private Logger logger = Logger.getLogger(RemoteServer1.class);

public void init(){
    Registry localRegistry = null;
    IServer1Interface server1 = null;
    try
    {
      int port = 1099;
      logger.info("Service Property rmiRegistryPort: " + port);
      server1 = (IServer1Interface)UnicastRemoteObject.exportObject(this, 0);
      logger.info("Locating registry");
      localRegistry = LocateRegistry.getRegistry();
      try
      {
        localRegistry.list();
      }
      catch (RemoteException localRemoteException2)
      {
        logger.info("Creating registry");
        try
        {
          localRegistry = LocateRegistry.createRegistry(port);
        }
        catch (RemoteException localRemoteException4)
        {
          logger.error("Server1 RemoteException. " + localRemoteException4);
          throw new RuntimeException("Server1 - Registry creation failed. ", localRemoteException4);
        }
      }
      logger.info("Binding");
      localRegistry.bind("Server1", server1);
    }
    catch (AlreadyBoundException localAlreadyBoundException)
    {
      logger.warn("Server1 - Object already bound." + localAlreadyBoundException);
      try
      {
        logger.info("Re-Binding");
        localRegistry.rebind("Server1", server1);
      }
      catch (AccessException localAccessException)
      {
        throw new RuntimeException("Server1 - AccessException while re-binding. ", localAccessException);
      }
      catch (RemoteException localRemoteException3)
      {
        throw new RuntimeException("Server1 - RemoteException while re-binding. ", localRemoteException3);
      }
    }
    catch (RemoteException localRemoteException1)
    {
      logger.error("Server1 RemoteException. " + localRemoteException1);
      throw new RuntimeException("Server1 - RemoteException. ", localRemoteException1);
    }
    logger.info("Remote Server1 ready");
}

}

这是我的第二个类(RemoteServer2.java)

代码语言:javascript
复制
package com.abc.rmi2;

import java.rmi.AccessException;
import java.rmi.AlreadyBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import org.apache.log4j.Logger;


public class RemoteServer2 implements IServer2Interface{

private Logger logger = Logger.getLogger(RemoteServer2.class);

public void init(){
    Registry localRegistry = null;
    IServer2Interface server2 = null;
    try
    {
      int port = 1099;
      logger.info("Service Property rmiRegistryPort: " + port);
      server2 = (IServer2Interface)UnicastRemoteObject.exportObject(this, 0);
      logger.info("Locating registry");
      localRegistry = LocateRegistry.getRegistry();
      try
      {
        localRegistry.list();
      }
      catch (RemoteException localRemoteException2)
      {
        logger.info("Creating registry");
        try
        {
          localRegistry = LocateRegistry.createRegistry(port);
        }
        catch (RemoteException localRemoteException4)
        {
          logger.error("Server2 RemoteException. " + localRemoteException4);
          throw new RuntimeException("Server2 - Registry creation failed. ", localRemoteException4);
        }
      }
      logger.info("Binding");
      localRegistry.bind("Server2", server2);
    }
    catch (AlreadyBoundException localAlreadyBoundException)
    {
      logger.warn("Server2 - Object already bound." + localAlreadyBoundException);
      try
      {
        logger.info("Re-Binding");
        localRegistry.rebind("Server2", server2);
      }
      catch (AccessException localAccessException)
      {
        throw new RuntimeException("Server2 - AccessException while re-binding. ", localAccessException);
      }
      catch (RemoteException localRemoteException3)
      {
        throw new RuntimeException("Server2 - RemoteException while re-binding. ", localRemoteException3);
      }
    }
    catch (RemoteException localRemoteException1)
    {
      logger.error("Server2 RemoteException. " + localRemoteException1);
      throw new RuntimeException("Server2 - RemoteException. ", localRemoteException1);
    }
    logger.info("Remote Server2 ready");
}

}

IServer1Interface和IServer2Interface实现java.rmi.remote。类RemoteServer1.java可以注册到RMI注册中心,但是在第二个类(RemoteServer2.java)中调用"localRegistry.rebind("Server2",server2)“行时,我得到了以下异常:

代码语言:javascript
复制
03-06-2014 18:03:43 ERROR RemoteServer2: - Server2 RemoteException. java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
java.lang.ClassNotFoundException: com.abc.rmi2.IServer2Interface (no security manager: RMI class loader disabled)

我使用以下代码在Tomcat服务器中运行:

代码语言:javascript
复制
URL url = new URL("file:///C:/temp/rmi/rmi1.jar");
    URL[] urls = {url};
    URLClassLoader child = new URLClassLoader(urls, this.getClass().getClassLoader());
    Class classToLoad = Class.forName ("com.abc.rmi.RemoteServer1", true, child);
    Method method = classToLoad.getDeclaredMethod ("init");
    Object instance = classToLoad.newInstance();
    Object result = method.invoke(instance);

    URL url2 = new URL("file:///C:/temp/rmi/rmi2.jar");
    URL[] urls2 = {url2};
    URLClassLoader child2 = new URLClassLoader(urls2, this.getClass().getClassLoader());
    Class classToLoad2 = Class.forName("com.abc.rmi2.RemoteServer2", true, child2);
    Method method2 = classToLoad2.getDeclaredMethod("init");
    Object instance2 = classToLoad2.newInstance();
    Object result2 = method2.invoke(instance2);

在启动Tomcat时,我没有定义任何安全管理器,也没有对Tomcat安全策略进行任何更改。我不明白的是,它如何能够很好地绑定第一个远程类,而不是第二个。我在许多地方读到,必须定义一个安全管理器才能使RMI工作,但它能够加载第一个类,而不会出现任何问题。为什么这个问题只发生在我试图绑定第二个类的时候。我还读到了属性'java.rmi.server.codebase',但我不确定第一个属性是如何加载的,即使我没有指定这个属性。有什么建议吗?

EN

回答 1

Stack Overflow用户

发布于 2014-03-06 18:25:46

注册表没有通过其CLASSPATH或代码库功能提供的第二个类。所以其中一个出了问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22221214

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档