很多人知道rmic工具(为远程对象生成 stub 和 skeleton),但是却很少人了解rmid,笔者在这里介绍一下rmid,并简单谈谈它的使用,rmid像rmic一样,
是一个可执行程序,用于启动系统激活进程,以便能够在 Java 虚拟机上注册和激活对象。 rmid的出现是为了解决分布式处理的性能问题,如果一个系统存在
着大量的分布式对象,而对象无限期存在于内存中并一直保持活动状态,这将占用太多系统资源,另外,客户机需要保存对对象的持久引用的能力,这样在一个
系统崩溃后可以重新建立对象之间的通讯。为了解决这些问题,就有了RMI激活架构,可以让对象在需要时激活,不需要时就钝化。关于RMI激活概念,读者可以
参看http://www.oneedu.cn/xxyd/Print.asp?ArticleID=4277&Page=1。
一般应用会把rmid和rmiregistry结合起来使用,一个专门用于激活和钝化,另外一个专门用于注册和查找,其实,rmid也有注册和查找对象的功能,所以
我们可以单独使用rmid来做rmi测试,我们先举一个例子说明,
先启动rmid,
rmid -J-Djava.security.policy=%LOCATION%/test.policy -port 1099
rmid在1099端口监听,默认是1098,现在用1099,目的很简单,替换rmiregistry。这里的LOCATION是指poliy文件存放的位置,
我们可以写一个全权开放的policy文件,
策略文件test.policy
grant {
permission java.security.AllPermission;
};
我们的server程序如下,
接口Server.java
package com.lxj;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Server extends Remote{
String say() throws RemoteException;
}
实现类Server1Impl.java
package com.lxj.test1;
import java.rmi.MarshalledObject;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.activation.Activatable;
import java.rmi.activation.ActivationDesc;
import java.rmi.activation.ActivationGroup;
import java.rmi.activation.ActivationGroupDesc;
import java.rmi.activation.ActivationGroupID;
import java.rmi.activation.ActivationID;
import java.util.Properties;
import com.lxj.Server;
public class Server1Impl extends Activatable implements Server {
public Server1Impl(ActivationID id, MarshalledObject data) throws RemoteException {
super(id, 0);
}
public String say() throws RemoteException {
System.out.println("begin say invoking");
return "hello,world";
}
public static void main(String[] args) throws Exception{
System.setSecurityManager(new RMISecurityManager());
Properties props = new Properties();
props.put("java.security.policy", "D:/ae_eclipse/workspace/test/bin/test.policy");
ActivationGroupDesc.CommandEnvironment ace = null;
ActivationGroupDesc group = new ActivationGroupDesc(props, ace);
System.out.println("Begin register group");
System.setProperty("java.rmi.activation.port","1099");
ActivationGroupID agi = ActivationGroup.getSystem().registerGroup(group);
System.out.println("End register group");
String location = "file:/D:/ae_eclipse/workspace/test/bin/";
MarshalledObject data = null;
ActivationDesc desc = new ActivationDesc(agi, "com.lxj.test1.Server1Impl", location, data);
Server server = (Server)Activatable.register(desc);
Naming.bind("Server",server);
System.out.println("Exported Server");
}
}
注:读者自己测试时请替换程序中的路径为自己本机的路径。
运行Server1Impl对服务进行注册,注意设置CLASSPATH,
java -Djava.security.policy=%LOCATION%/test.policy -Djava.rmi.server.codebase=file:/%LOCATION_2%/ com.lxj.test1.Server1Impl
LOCATION_2是指class文件的位置,运行完毕,如果没有错误表明已经注册激活组成功。
现在我们可以用客户端类来调用我们的服务,
package com.lxj.test1;
import java.rmi.Naming;
import com.lxj.Server;
public class Client1 {
public static void main(String[] args) throws Exception {
Server server = (Server) Naming.lookup("Server");
//如果是远程服务,可以切换用下面注释掉的代码
//Server server = (Server)java.rmi.registry.LocateRegistry.getRegistry("localhost",1099).lookup("Server");
System.out.println(server.say());
}
}
运行Client1以后,我们会发现在服务器进程列表中多了一个java进程,这个进程是rmid的子进程,每个激活组都会有一个jvm进程。
下面我们可以让rmid和rmiregistry一起工作,不过我们先要小小地调整一下Server1Impl.java代码,把
System.setProperty("java.rmi.activation.port","1099");这句话注释掉然后重新编译,因为现在rmiregistry要使用1099端口,
rmid还是使用它的1098,当然,这些端口号都可以修改。
先启动rmid,
rmid -J-Djava.security.policy=test.policy
然后启动rmiregistry
rmiregistry
再注册激活组和注册虚拟引用
java -Djava.security.policy=%LOCATION%/test.policy -Djava.rmi.server.codebase=file:/%LOCATION_2%/ com.lxj.test1.Server1Impl
运行Client1就会得到前面一样的结果。
最后要说明的是rmid(父进程)的系统参数会自动传给激活组对应的java子进程,比如rmid -J-Dcorp=lxj,我们可以在我们的服务类中通过
System.getProperties().getProperty("corp")取到。
分享到:
- 2007-06-26 18:13
- 浏览 3084
- 评论(1)
- 论坛回复 / 浏览 (1 / 5199)
- 查看更多
相关推荐
本文将详细介绍几个常用的JDK命令及其使用方法,包括`rmic`、`rmid`、`rmiregistry`、`serialver`以及`jarsigner`等,帮助读者更好地理解和运用这些命令。 #### 1. rmic - 生成RMI存根和骨架文件 **简介**:`rmic`...
本篇文章将详细介绍如何使用消息队列机制来自行编写具有一定长度(大约1K左右)的消息发送和接收程序,并通过具体的代码示例来加深理解。 #### 消息队列的概念与工作原理 消息队列是由操作系统维护的一个消息列表...
7. Java图形用户界面(GUI):介绍了使用Swing包创建GUI的基础,如`FlowLayout`布局管理器的使用。 8. Java异常处理:解释了Java异常处理机制,包括`try`,`catch`,`finally`和自定义异常。 9. Java I/O流:解释...
本文将详细介绍如何在Linux环境下使用共享内存,并解释相关的API函数及其使用方法。 #### 创建共享内存 为了使用共享内存,通常需要经历以下几个步骤: 1. **开辟共享内存**:通过`shmget()`函数来创建或获取共享...
4. 问题排查:常见的问题包括端口冲突、注册表未启动、网络不通等,可以通过`rmid`、`rmiregistry`的日志进行分析。 总结,RMI是Java中实现分布式计算的重要工具,它简化了跨网络对象交互的过程。理解并熟练掌握RMI...
3. **-port[端口]**:指定`rmid`使用的端口号,默认为1098端口。 4. **-stop**:停止由-port选项指定端口的当前`rmid`守护进程;如果没有指定端口,则停止监听1098端口的`rmid`守护进程。 #### 三、`rmiregistry`...
这篇文档详细介绍了在C语言中使用信号量的一些关键函数,包括`semget()`、`ftok()`、`semctl()`和`semop()`。 1. **创建信号量**: `semget()`函数用于创建或获取一个信号量集。它需要三个参数:`key_t key`用于...
9. **资源管理**:共享内存段在创建后需要妥善管理,包括清理不再使用的内存段(使用`shmctl`的IPC_RMID命令或`CloseHandle`),以及处理进程异常退出时的内存泄漏问题。 10. **应用场景**:共享内存常用于数据库...
shmctl(myshm, IPC_RMID, 0); ``` ### 信号量(Semaphore) 信号量是一种同步机制,用于解决多个进程对共享资源的竞争问题。在给定的代码片段中并没有直接使用信号量,但在多进程环境中,为了保护共享内存免受并发...
下面将详细介绍这些机制的使用方法和相关函数。 ### 1. 信号量(Semaphore) 信号量是一种同步原语,用于控制对共享资源的访问。在Linux中,主要通过以下函数进行操作: - **创建有名信号量**: 使用`sem_open()...
8. **资源清理**:在主函数中,使用`msgctl`函数和`IPC_RMID`参数来删除消息队列,释放系统资源。 9. **实验步骤与调试**:实验步骤包括分析需求、设计代码、编译、调试和运行。在shell环境中进行这些操作,使用如`...
这些通信方式被广泛应用于网络应用程序的设计中,下面将分别介绍这三种方式。 ##### 1. 共享内存 (Shared Memory) 共享内存是一种高效的进程间通信方式,它允许两个或多个进程共享同一段内存区域。这种方式最大的...
- **删除共享内存区**:使用`shmctl()`函数中的`IPC_RMID`选项删除共享内存区。 #### 六、套接字(Sockets) 除了上述本地IPC机制外,《UNIX网络编程卷2》还详细介绍了套接字(Sockets),这是一种用于网络进程间...
下面将详细介绍这些知识点以及如何在C中实现加锁版本的共享内存操作。 1. **共享内存创建**: 使用`shmget`函数创建共享内存。这个函数需要三个参数:键(key)、内存大小(size)和权限(flags)。键通常是通过`...
7. 使用 `msgctl()` 函数(例如 `IPC_RMID` 标志)删除消息队列,以释放资源。 在进行实验时,需要注意消息队列的权限控制、消息的顺序与类型匹配,以及处理可能出现的竞争条件和同步问题。 通过这样的实验,...
本文将详细介绍如何在Linux环境下,使用C语言进行消息队列的接口封装。 首先,我们需要了解与消息队列相关的几个主要函数: 1. `msgget`:这个函数用于创建一个新的消息队列或者获取已存在的消息队列的标识符。它...
在Linux操作系统中,进程间通信(IPC,Inter-Process Communication)是...以上就是关于“Linux C 进程间通信 消息队列”的详细介绍,通过理解和实践,你将能够熟练地在C语言环境中运用消息队列进行进程间的有效通信。
在本文中,我们将详细介绍 ftok 函数的原型、参数、返回值、使用方法以及示例程序。 ftok 函数的原型为: key_t ftok(char *fname, int id) 其中,fname 是一个文件名,id 是一个整数值,虽然 id 是 int 类型,...
这份“远程java接口说明.pdf”文档详细介绍了如何使用Java API来实现远程接口操作。以下是其中涉及到的关键知识点: 一、设置接口访问用户名和密码: 为了确保安全性和授权,远程接口通常需要身份验证。在Java中,...
在本节中,我们将详细介绍进程通信的各种方式,包括管道、命名管道、消息队列、信号灯和共享内存等。 一、管道 管道是一种半双工的通信方式,即数据只能从一端流向另一端。管道可以分为无名管道和命名管道两种。...