被一个java.rmi.RemoteException引发的窘境,“坚持”就有希望!

本文记录了一次使用RMI进行远程方法调用时遇到的问题及解决过程。主要问题是由于环境变量配置冲突导致的java.rmi.RemoteException异常,通过调整环境变量最终解决了问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      今天第一次使用rmi编写远程方法调用写程序,我事先想测试rmi编写的简单例子,代码如下:

  /*
 *Create on Dec 31, 2008
 *Copyright 2009 Quasar20063501.All Rights reserved
 *
 *weizhaozhe
 */

 

//wzz.server.Server.java
package wzz.server;

import java.rmi.*;

import wzz.service.*;

public class Server {
 public static void main(String args[]){
  try{
   RmtServiceImpl service=new RmtServiceImpl();                            //远程接口Remote实现类对象
   String registration="rmi://localhost:8888/RmtService";
   Naming.rebind(registration, service);                                                //注册远程服务
  }catch(RemoteException re){
   System.out.println("There is a RemoteException happened!/n");
   System.out.println("Details:"+re);
  }catch(Exception e){
   System.out.println("There is a Exception happened!/n");
  }
 }
}

 

基本没有任何复杂的功能,就是按照Java API的QuickStart编写的, 但在运行时却一直抛出java.rmi.RemoteException异常。于是从头检查了一下代码,没发现任何错误,就去找了对这个比较熟悉的同学,同学“看了又看”,也没发现错误,于是我们一直在研究,从晚上5:00一直到7:00,之后我自己有看了一段时间,最后还是没发现错误,确定是Naming.rebind()抛出的异常,是找不到与服务对象相对应的分发类xxx_stub.class,因为rebind其实调用的是此类的rebind方法,所以一直抛出异常,但是我已经使用rmic工具生成了XXX_stub.class了,在bin目录下是可见的,为什么呢?难道是没有配置Path,但是我们查到由配置了,搞的头晕脑涨,不知是怎么了,最后室友还说是RP(人品)问题,哎,最后,原来是曾经配置的Path与现在的Path发生冲突了吧,反正我把环境变量整理一下就好了,真是可恨可笑,3个小时,发现了这么个“异常”。

 

    虽然现在被这个问题弄得有些消沉,但还是想和大家分享一我的经历,我想大家在编程时也会经常发生这种状况,遇到了一时怎么也解决不了的错误,可能花了很长时间,这种时候一定很难受,但是我们一定要坚持啊,换一种思路,可能就豁然开朗了呢!第一次发表博客,请大家多多指教啊!

 

   最后在2009年希望我们的身体健康,技术长进,万事如意吧!元旦快乐!

 

 

 

 

 

 


 

<think>我们正在讨论Java RMI中的`java.rmi.server.hostname`系统属性。根据引用,这个属性用于指定RMI服务器在注册RMI注册表时使用的主机名或IP地址。当RMI服务器在具有多个网络接口(例如,多个IP地址)的机器上运行时,或者当服务器位于NAT或防火墙后面时,这个属性尤为重要。如果不设置,RMI可能会选择一个不正确的网络接口(如127.0.0.1或私有IP),导致远程客户端无法连接。 配置方法有两种: 1. 在启动JVM时通过命令行参数设置:`-Djava.rmi.server.hostname=你的公网IP或域名` 2. 在代码中设置系统属性:`System.setProperty("java.rmi.server.hostname", "你的公网IP或域名");` 注意:这个属性必须在创建RMI注册表或绑定远程对象之前设置,因为RMI在导出远程对象时会使用这个主机名。 例如,在代码中设置: ```java public void start() throws Exception { System.setProperty("java.rmi.server.hostname", "118.31.168.198"); LocateRegistry.createRegistry(30101); RMIServer h = new RMIServer(); Naming.rebind("rmi://127.0.0.1:30101/Feng", h); System.out.println("RMI服务在30101端口启动"); } ``` 或者,在启动命令中设置: ``` java -Djava.rmi.server.hostname=118.31.168.198 -jar your_application.jar ``` 在分布式测试工具如JMeter中,这个设置同样重要,因为它确保从机(slave)能够正确地连接到主机(master)的RMI服务。 相关问题: 1. 为什么在分布式JMeter测试中必须设置`java.rmi.server.hostname`? 2. 如何诊断和解决Java RMI连接被拒绝的问题? 3. 除了设置`java.rmi.server.hostname`,还有哪些配置可以确保RMI服务在复杂网络环境中正常工作? 4. RMI注册表(Registry)和远程对象绑定(bind/rebind)之间有什么关联? 5. 在Docker容器中运行RMI服务时,如何配置`java.rmi.server.hostname`?</think>### Java RMI 服务器主机名参数详解 `java.rmi.server.hostname` 是 Java RMI(远程方法调用)框架中的关键系统属性,用于指定 RMI 服务器对外暴露的主机名或 IP 地址。当服务器有多个网络接口或位于 NAT/防火墙后时,必须正确配置该参数才能确保客户端正常连接。 #### 核心作用 1. **地址绑定控制** 指定 RMI 服务器在注册表中发布的网络地址(而非默认的本地地址) ```java // 示例:设置服务器公网IP System.setProperty("java.rmi.server.hostname", "118.31.168.198"); ``` 2. **解决连接问题** 当客户端收到 "Connection refused" 错误时(如引用[2]所述),通常是因为服务器注册了不可达的地址(如 127.0.0.1) 3. **分布式系统支持** 在 JMeter 分布式测试等场景中(引用[3][5]),确保从机能解析到主机的正确地址 #### 配置方法 **方式1:代码中动态设置(推荐)** 在创建 RMI 注册表前设置系统属性: ```java public void startRMIServer() throws Exception { // 关键配置:设置主机名/IP System.setProperty("java.rmi.server.hostname", "118.31.168.198"); // 创建注册表并绑定服务 LocateRegistry.createRegistry(30101); Naming.rebind("rmi://118.31.168.198:30101/ServiceName", new ServiceImpl()); System.out.println("RMI服务在30101端口启动"); } ``` **方式2:JVM 启动参数** 通过 `-D` 参数指定: ```bash java -Djava.rmi.server.hostname=118.31.168.198 -jar your_app.jar ``` **方式3:环境变量配置** 适用于容器化部署(引用[4]): ```bash # Tomcat示例 export CATALINA_OPTS="$CATALINA_OPTS -Djava.rmi.server.hostname=192.168.40.103" ``` #### 注意事项 1. **时机要求** 必须在 `LocateRegistry.createRegistry()` 或 `Naming.rebind()` 前设置,否则无效[^1] 2. **网络环境** - 公网部署需使用公网 IP 或域名 - 云环境需配合安全组开放端口 3. **客户端匹配** 客户端连接地址需与服务器配置一致: ```java // 客户端连接示例 String rmiUrl = "rmi://118.31.168.198:30101/ServiceName"; Service service = (Service) Naming.lookup(rmiUrl); ``` #### 常见问题解决 - **错误:ObjID already in use** 检查端口冲突(引用[4]),确保每次重启前注销服务 - **分布式测试失败** JMeter 需在所有节点设置一致的主机名(引用[3][5]) - **NAT 穿透问题** 在防火墙后部署时,需同时配置端口转发规则 ### 相关问题 1. 如何诊断 Java RMI 的 "Connection refused" 错误? 2. 在 Docker 容器中部署 RMI 服务需要哪些特殊配置? 3. RMI 与 Web Service 在分布式通信中的优劣比较? 4. 如何实现 RMI 服务的动态负载均衡? 5. JMeter 分布式测试中除了主机名还需要哪些关键配置?[^3][^5] [^1]: 引用自代码示例,说明配置时机的重要性 [^2]: 引用关于 RMI 连接问题的通用解决方案 [^3]: 引用 JMeter 分布式测试中的实际应用场景 [^4]: 引用容器环境配置示例 [^5]: 引用分布式测试的端口配置注意事项
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值