Vous êtes sur la page 1sur 13

Java RMI

RMI (Remote Method Invocation) uma das abordagens da tecnologia Java para prover as
funcionalidades de uma plataforma de objetos distribudos. Esse sistema de objetos
distribudos faz parte do ncleo bsico de Java desde a verso J!" #.#$ com sua %&I sendo
especificada atravs do pacote java.rmi e seus subpacotes.
%travs da utiliza'o da ar(uitetura RMI$ possvel (ue um objeto ativo em uma m(uina
virtual Java possa interagir com objetos de outras m(uinas virtuais Java$
independentemente da localiza'o dessas m(uinas virtuais.
)o desenvolvimento de uma aplica'o cliente*servidor usando Java RMI$ como para
(ual(uer plataforma de objetos distribudos$ essencial (ue seja definida a interface de
servi'os (ue sero oferecidos pelo objeto servidor.
+s servi'os especificados pela interface RMI devero ser implementados atravs de uma
classe Java. )essa implementa'o dos servi'os preciso indicar (ue objetos dessa classe
podero ser acessados remotamente.
,om a interface estabelecida e o servi'o implementado$ possvel criar as aplica'-es
cliente e servidor RMI.
% e.ecu'o da aplica'o cliente*servidor em RMI re(uer$ alm da e.ecu'o da aplica'o
cliente e da e.ecu'o da aplica'o servidor$ a e.ecu'o do servi'o de registro de RMI.
%lm do princpio bsico de e.ecu'o de aplica'-es RMI$ a ar(uitetura RMI oferece
facilidades para opera'o com c/digo disponibilizado de forma distribuda e ativa'o
din0mica$ alm de outros servi'os distribudos.
1 interessante observar como padr-es de programa'o distribuda$ como a fbrica de
objetos remotos e o padro de callback$ so trabal2ados em aplica'-es RMI.
3eja tambm$ da documenta'o do Java$ os recursos 4%5 RMI$ RMI tools e o RMI 6uide.
Arquitetura RMI
% ar(uitetura RMI oferece a transpar7ncia de localiza'o atravs da organiza'o de tr7s
camadas entre os objetos cliente e servidor8
#. % camada de stub/skeleton oferece as interfaces (ue os objetos da aplica'o usam
para interagir entre si9
:. % camada de referncia remota o middleware entre a camada de stub;s<eleton e
o protocolo de transporte. 1 nesta camada (ue so criadas e gerenciadas as
refer7ncias remotas aos objetos9
=. % camada do protocolo de transporte oferece o protocolo de dados binrios (ue
envia as solicita'-es aos objetos remotos pela rede.
Essa figura ilustra a organiza'o dessas tr7s camadas em uma aplica'o RMI8
Definindo a interface para um servio
RMI
% especifica'o de uma interface remota e(uivalente > defini'o de (ual(uer interface em
Java$ a no ser pelos seguintes detal2es8
% interface dever$ direta ou indiretamente$ estender a interface Remote9
?odo mtodo da interface dever declarar (ue a e.ce'o RemoteE.ception @ou uma
de suas superclassesA pode ser gerada na e.ecu'o do mtodo.
Esse e.emplo ilustra a defini'o de uma interface remota para um objeto (ue contm um
contador inteiro. Esse contador manipulado por (uatro mtodos8
#. set()$ para definir um valor inicial para o contador9
:. reset()$ para reiniciar o contador com o valor B9
=. get()$ para consultar o valor do contador sem alter*lo9 e
C. increment()$ (ue l7 o valor atual do contador e incrementa*o.
// Count Interface
import java.rmi.*;
public interface Count extends Remote {
void set(int val) throws Remote!ception;
void reset() throws Remote!ception;
int get() throws Remote!ception;
int increment() throws Remote!ception;
"
Implementando o servio remoto em RMI
% implementa'o do servi'o se d atravs da defini'o de uma classe (ue implementa a
interface especificada. )o entanto$ alm de implementar a interface especificada$ preciso
incluir as funcionalidades para (ue um objeto dessa classe possa ser acessado remotamente
como um servidor.
% implementa'o da interface remota se d da mesma forma (ue para (ual(uer classe
implementando uma interface Java$ ou seja$ a classe fornece implementa'o para cada um
dos mtodos especificados na interface.
%s funcionalidades de um servidor remoto so especificadas na classe abstrata
RemoteDerver$ do pacote java.rmi.server. Em objeto servidor RMI dever estender essa
classe ou$ mais especificamente$ uma de suas subclasses. Ema subclasse concreta de
Remote#erver oferecida no mesmo pacote EnicastRemote+bject$ (ue permite
representar um objeto (ue tem uma nica implementa'o em um servidor @ou seja$ no
replicado em vrios servidoresA e mantm uma cone.o ponto*a*ponto com cada cliente
(ue o referencia.
?ipicamente$ a declara'o de uma classe (ue implementa um servidor remoto RMI ter a
forma
pu$lic class ... e!tends %nicastRemote&$ject implements ... {
...
"

Esse e.emplo oferece uma possvel implementa'o para a interface remota previamente
especificada.
// CountImpl.java
import java.rmi.*;
import java.rmi.server.%nicastRemote&$ject;
public class CountImpl extends UnicastRemoteObject
implements Count {
private int sum;

public CountImpl() throws Remote!ception {
"

public void set(int val) throws Remote!ception {
sum ' val;
"

public void reset() throws Remote!ception {
sum ' (;
"

public int get() throws Remote!ception {
return sum;
"

public int increment() throws Remote!ception {
return sum));
"
"
// Count Interface
import java.rmi.*;
public interface Count extends Remote {
void set(int val) throws Remote!ception;
void reset() throws Remote!ception;
int get() throws Remote!ception;
int increment() throws Remote!ception;
"
Definio de objetos clientes e servidores
em RMI
Ema vez (ue a interface remota esteja definida e a classe (ue implementa o servi'o remoto
ten2a sido criada$ o pr/.imo passo no desenvolvimento da aplica'o distribuda
desenvolver o servidor RMI$ uma classe (ue crie o objeto (ue implementa o servi'o e
cadastre esse servi'o na plataforma de objetos distribudos.
+ desenvolvimento de um cliente RMI re(uer essencialmente a obten'o de uma refer7ncia
remota para o objeto (ue implementa o servi'o$ o (ue ocorre atravs do cadastro realizado
pelo servidor. Ema vez obtida essa refer7ncia$ a opera'o com o objeto remoto
indistingFvel da opera'o com um objeto local.
&ara (ue um servi'o oferecido por um objeto possa ser acessado remotamente atravs de
RMI$ preciso tambm as classes au.iliares internas de stubs e skeletons $ responsveis pela
comunica'o entre o objeto cliente e o objeto (ue implementa o servi'o$ conforme descrito
na apresenta'o da ar(uitetura RMI.
Desenvolvimento de servidor RMI
Em objeto servidor RMI simples deve realizar as seguintes tarefas8
#. ,riar uma inst0ncia do objeto (ue implementa o servi'o9
:. !isponibilizar o servi'o atravs do mecanismo de registro.
Esse e.emplo de servidor RMI para o contador remoto cria uma inst0ncia da
implementa'o do servi'o e coloca*a > disposi'o de potenciais clientes$ registrando*o no
registrG RMI.
&ode 2aver situa'-es em (ue no seja interessante registrar cada implementa'o de um
servi'o no registry * por e.emplo$ (uando o servidor no sabe (uantos objetos criar de
antemo ou (uando a (uantidade de pe(uenos servi'os registrados e to grande (ue pode
tornar a busca por um servi'o ineficiente. )essas situa'-es$ pode ser interessante utilizar
uma fbrica de objetos remotos.
riando stubs e skeletons
Ema vez (ue a interface e a classe do servi'o ten2am sido criadas e compiladas para
bytecodes usando um compilador Java convencional$ possvel criar os correspondentes
stubs e skeletons. &ara tanto$ utiliza*se o aplicativo compilador RMI$ rmic$ disponibilizado
juntamente com o <it de desenvolvimento Java.
Esse e.emplo ilustra o processo de compila'o RMI para o servi'o do contador remoto.
Ema classe stub oferece implementa'-es dos mtodos do servi'o remoto (ue so invocadas
no lado do cliente. Internamente$ esses mtodos empacotam (marshall) os argumentos para
o mtodo e os envia ao servidor. % implementa'o correspondente no lado servidor$ no
skeleton$ desempacota (unmarshall) os dados e invoca o mtodo do servi'o. % partir da
verso #.: de Java$ o skeleton dei.ou de ser necessrio para a opera'o de RMI.
+btido o valor de retorno do servi'o$ o servidor empacota e envia esse valor para o mtodo
no stub$ (ue ainda estava aguardando esse retorno. +btido o valor de retorno no stub$ esse
desempacotado e retornado > aplica'o cliente como resultado da invoca'o remota.
Internamente$ o processo de marshalling utiliza o mecanismo de serializa'o de Java.
%ssim$ argumentos e valores de retorno de mtodos remotos invocados atravs de RMI
esto restritos a tipos primitivos de Java e a objetos de classes (ue implementam
#eriali*a$le.
!"emplo# criao de stubs e skeletons
,onsidere a implementa'o do servi'o (ue foi previamente definida. + primeiro passo para
a cria'o do stub e do skeleton para esse servi'o obter a classe compilada$ (ue por sua vez
precisa da classe da interface8
+ javac Count.java
+ javac CountImpl.java

,om a classe CountImpl.class disponvel$ a e.ecu'o do comando
+ rmic CountImpl

gera as classes CountImpl,#tu$.class e CountImpl,#-el.class$ correspondendo
respectivamente ao stub e ao skeleton para o servi'o. + stub dever ser disponibilizado
junto ao c/digo do cliente RMI$ en(uanto (ue o skeleton dever estar disponvel junto ao
c/digo do servidor.
lientes RMI
% principal etapa no desenvolvimento de uma aplica'o cliente RMI a obten'o da
refer7ncia remota para o objeto @remotoA (ue implementa o servi'o desejado. &ara tanto$ o
cliente RMI usa o servi'o padro oferecido pelo mecanismo de registro de nomes de
servi'os.
Ema vez (ue a refer7ncia remota seja obtida$ ela pode ser convertida (downcast) para uma
refer7ncia para a interface (ue especifica o servi'o. % partir de ento$ os mtodos
oferecidos pelo servi'o remoto so invocados da mesma forma (ue ocorre para objetos
locais.
Esses e.emplos ilustram o desenvolvimento de c/digo cliente em RMI. )o primeiro
e.emplo desenvolve*se um cliente RMI (ue simplesmente invoca o mtodo reset()
atravs de uma refer7ncia remota para o objeto servidor. )o e.emplo seguinte$ o cliente
utiliza os mtodos para modificar e obter o valor do contador remoto.
Esse e.emplo alternativo ilustra a utiliza'o de RMI a partir de um cliente desenvolvido
como um applet. )esse applet$ um campo de te.to mostra o valor do contador no objeto
servidor. !ois bot-es so fornecidos$ um para incrementar o valor mil vezes @DtartA e outro
para obter o valor atual do contador @6etA.
Re$istro
+ aplicativo rmiregistrG faz parte da distribui'o bsica de Java. ?ipicamente$ esse
aplicativo e.ecutado como um processo de fundo @em backgroundA (ue fica aguardando
solicita'-es em uma porta$ (ue pode ser especificada como argumento na lin2a de
comando. De nen2um argumento for especificado$ a porta #BHH usada como padro.
+ aplicativo rmiregistr. uma implementa'o de um servio de nomes para RMI. +
servi'o de nomes uma espcie de diret/rio$ onde cada servi'o disponibilizado na
plataforma registrado atravs de um nome do servio$ uma string nica para cada objeto
(ue implementa servi'os em RMI.
&ara ter acesso ao servi'o de nomes a partir de uma classe Java$ so oferecidos dois
mecanismos bsicos. + primeiro utiliza a classe )aming$ do pacote java.rmi. + segundo
mecanismo utiliza as facilidades oferecidas atravs do pacote java.rmi.registrG.
// CountReset.java
import java.rmi.registr..*;
public class CountReset {
public static void main(String args[]) {
tr. {
// /ocali*a o servi0o pelo nome atrav1s do
// rmiregistr. e!ecutando na m23uina local
// e operando na porta default (4(55)
Registr. r ' /ocateRegistr..getRegistr.();
Count m.Count ' (Count) r.loo-up(6Count((46);

// Reali*a opera07es com o$jeto remoto
m.Count.reset();
"
catch(!ception e) {
e.print#tac-8race();
"
#.stem.e!it(();
"
"
// CountClient.java
import java.rmi.*;
public class CountClient {
public static void main(String args[]) {
tr. {
// /ocali*a o servi0o pelo nome atrav1s do
// rmiregistr. e!ecutando na m23uina local
// e operando na porta default (4(55)
Remote remRef ' 9aming.loo-up(6Count((46);
// Converte refer:ncia do tipo 6Remote6 para
// uma refer:ncia do tipo da interface do
// servi0o
Count m.Count ' (Count) remRef;

// Reali*a opera07es com o$jeto remoto
int init;alue ' m.Count.get();
#.stem.out.print(6<e 6 ) init;alue ) 6 para 6);
long start8ime ' #.stem.current8ime=illis();
for (int i ' ( ; i > 4((( ; i)) )
m.Count.increment();
long stop8ime ' #.stem.current8ime=illis();
#.stem.out.println(m.Count.get());

// Calcula tempo m1dio por incremento
#.stem.out.println(6?vg @ing ' 6
) ((stop8ime A start8ime)/4(((f)
) 6 msecs6);
"
catch(!ception e) {
e.print#tac-8race();
"
#.stem.e!it(();
"
"
// ?ppletClient.java
import java.rmi.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class ppletClient extends pplet
implements ?ction/istener {
Count remCount;
8e!tBield tfCnt;
Cutton $#tartD $Eet;
#tring $sla$el ' 6#tart6;
#tring $gla$el ' 6Eet6;
public void init() {
tr. {
set/a.out(new Erid/a.out(FDF));
add(new /a$el(6CountG6));
tfCnt ' new 8e!tBield(H);
tfCnt.setdita$le(false);
add(tfCnt);
$#tart ' new Cutton($sla$el);
$#tart.add?ction/istener(this);
$Eet ' new Cutton($gla$el);
$Eet.add?ction/istener(this);
add($#tart);
add($Eet);
show#tatus(6Cinding remote o$ject6);
remCount ' (Count) 9aming.loo-up(6Count((46);
tfCnt.set8e!t(Integer.to#tring(remCount.get()));
"
catch (!ception e) {
e.print#tac-8race();
"
"
public void paint() {
tr. {
tfCnt.set8e!t(Integer.to#tring(remCount.get()));
"
catch (!ception e) {
e.print#tac-8race();
"
"
public void action!erformed (ction"vent ev) {
tr. {
#tring $otao ' ev.get?ctionCommand();
if ($otao.e3uals($sla$el)) {
show#tatus(6Incrementing...6);
for (int i ' ( ; i > 4((( ; i)) )
remCount.increment();
show#tatus(6<one6);
"
else {
show#tatus(6Current count6);
paint();
"
"
catch (!ception e) {
e.print#tac-8race();
"
"
"
%perao com objetos remotos em RMI
)o primeiro e.emplo de opera'o de aplica'-es distribudas usando RMI$ assumiu*se (ue
as aplica'-es clientes$ servidor e de registro eram processos distintos mas (ue estavam
e.ecutando em uma mesma m(uina. %lm disto$ considerou*se tambm (ue todas as
classes necessrias para a opera'o das aplica'-es estavam localizadas em algum diret/rio
do C/?##@?8I.
)o caso de e.ecu'o em m(uinas separadas$ 2 duas formas de fazer a distribui'o das
classes de modo (ue clientes e servidores possam e.ecutar corretamente. )a primeira
forma$ a estratgia distribuir e.plicitamente as classes necessrias e inclu*las em
diret/rios onde elas possam ser localizadas (uando necessrio. &o lado cliente$ essas
classes complementares seriam a interface do servi'o e o stub para a implementa'o do
servi'o. &o lado servidor$ seriam essas as classes de implementa'o do servi'o @e o
correspondente skeleton$ para vers-es anteriores > #.:A.
% outra forma utilizar os mecanismos de carregamento din0mico de classes distribudas$
em alternativa ao class loader padro da m(uina virtual Java. &or e.emplo$ se a e.ecu'o
do cliente se d atravs de um applet$ o ?ppletClass/oader oferece as funcionalidades
necessrias para localizar uma classe (ue est localizada no mesmo diret/rio de onde foi
carregada a classe original.
Em RMI$ 2 uma alternativa adicional de se utilizar o R=IClass/oader$ (ue permite o
carregamento de stubs e skeletons a partir de um ERI @especificado atravs da propriedade
java.rmi.server.code$aseA. Essa propriedade deve ser estabelecida para a m(uina
virtual Java (ue ir e.ecutar o servidor$ como em
+ java A<java.rmi.server.code$ase'httpG//meuhost/meudir/
Count#erver

!este modo$ (uando o servidor realizar o cadastro do servi'o no registry$ esse codebase
ser embutido na refer7ncia do objeto. 5uando o cliente obtiver a refer7ncia ao objeto
remoto do registry e seu class loader fal2ar em localizar a classe stub no ,I%DD&%?J
local$ sua m(uina virtual Java far uma cone.o J??& com meuhost para obter a classe
correspondente @assim como outras classes eventualmente necessrias para e.ecu'o do
servi'o no lado clienteA.
!e forma similar$ caso o rmiregistr. estivesse operando em outra m(uina$ distinta
da(uela onde as aplica'-es clientes e servidor estivessem e.ecutando$ seria necessrio
especificar no c/digo das aplica'-es a m(uina (ue e.ecuta rmiregistr.$ seja atravs do
mtodo getRegistr.() da classe /ocateRegistr. ou atravs da especifica'o de ERI no
protocolo RMI nos mtodos da classe 9aming .
,omo para (ual(uer situa'o na (ual a m(uina virtual Java ir carregar classes localizadas
de forma distribuda$ preciso adicionalmente estabelecer (ual a poltica de seguran'a para
operar com c/digo proveniente das outras m(uinas. Essa poltica ser enfor'ada pelo
gerenciador de seguran'a$ (ue pode ser definido pela invoca'o do mtodo correspondente
antes de (ual(uer invoca'o a mtodos de RMI8
#.stem.set#ecurit.=anager(new R=I#ecurit.=anager());

+ uso dessas facilidades pode ser apreciado nos e.emplos modificados para o c/digo do
servidor e cliente da aplica'o do contador distribudo. % especifica'o da interface e a
implementa'o do servi'o permanecem inalteradas para esses e.emplos.
'ervio RMI para ativao de objetos
)a primeira especifica'o de RMI @J!" #.#A$ era necessrio (ue um servi'o oferecido por
um objeto fosse e.plicitamente ativado em alguma m(uina virtual Java e ento fosse
cadastrado em um servi'o de registro. Essa foi a forma adotada no e.emplo anterior para
e.ecu'o de uma aplica'o RMI.
+ problema com essa abordagem ocorre principalmente (uando$ por algum motivo no
previsto$ o servi'o torna*se indisponvel. )este caso$ no 2 como sinalizar o cliente ou o
registro sobre esse fato. % nica indica'o seria$ no momento em (ue o cliente tentasse
utilizar a refer7ncia remota$ a ocorr7ncia de uma e.ce'o8
java.rmi.Connect!ceptionG Connection refused to hostG (etc.)

+ servi'o de ativa'o$ disponvel a partir de J!" #.:$ permite contornar essa limita'o.
%travs da utiliza'o dos recursos disponveis nesse servi'o$ possvel criar
automaticamente um objeto remoto com a implementa'o do servi'o apenas (uando 2 a
solicita'o para obter a refer7ncia para um objeto da(uela classe. Esando o mesmo
mecanismo$ possvel reiniciar a e.ecu'o de objetos remotos (ue ten2am encerrado sua
e.ecu'o em decorr7ncia de alguma fal2a do sistema.
&ara utilizar o servi'o de ativa'o RMI$ preciso usar o conjunto de classes do pacote
java.rmi.activation para o servidor com ativa'o din0mica. + servi'o de ativa'o
propriamente dito e.ecutado em uma m(uina virtual Java com um objeto da classe
java.rmi.activation.%ctivator. % aplica'o rmid$ distribuda na plataforma Java :$ um
daemon (ue implementa esse servi'o.
3eja tambm$ da documenta'o Java$ tutoriais sobre Remote +bject %ctivation.
'ervios de %bjetos RMI
RMI oferece alguns servi'os (ue podem ser utilizados pela aplica'o usando essa
plataforma de objetos distribudos. +s tr7s servi'os bsicos oferecidos so o mecanismo de
registro$ o mecanismo de ativa'o de objetos e o mecanismo de garbage collection
distribudo.
!"ecuo de aplicao RMI
)a e.ecu'o da aplica'o RMI desenvolvida$ preciso ter vrios processos e.ecutando
simultaneamente$ conforme ilustrado abai.o8
+ registro RMI @rmiregistr.A e.ecuta isoladamente em uma m(uina virtual Java. +
servidor da aplica'o$ assim como a implementa'o do servi'o$ esto e.ecutando em outra
m(uina virtual Java9 sua intera'o com o registro @ao invocar o mtodo $ind()A se d
atravs de uma refer7ncia remota. !a mesma forma$ cada aplica'o cliente pode ser
e.ecutada em sua pr/pria m(uina virtual Java9 suas intera'-es com o registro @mtodo
loo-up()A e com a implementa'o do servi'o @usando os correspondentes stub e skeletonA
do*se tambm atravs de refer7ncias remotas.
&ortanto$ para e.ecutar uma aplica'o RMI preciso inicialmente disponibilizar o servi'o
de registro RMI. &ara tanto$ o aplicativo rmiregistr. deve ser e.ecutado8
(ni" Dos
+ rmiregistr. J + start rmiregistr.
+ smbolo J ao final do comando Eni.$ assim como o start no comando !os$ do incio >
e.ecu'o do comando especificado como um Kprocesso de fundoK @em backgroundA.
,om o rmiregistr. disponvel$ o servidor pode ser e.ecutado. &ara tanto$ essa m(uina
virtual Java dever ser capaz de localizar e carregar as classes do servidor$ da
implementa'o do servi'o e do skeleton8
(ni" Dos
+ java Count#erver J + start java Count#erver
%p/s a e.ecu'o desse comando$ a mensagem Count #erver read.. dever surgir na
tela$ indicando (ue o servidor obteve sucesso na cria'o e registro do servi'o e portanto
est apto a responder >s solicita'-es de clientes.
4inalmente$ com o servidor j 2abilitado para responder >s solicita'-es$ o c/digo cliente
pode ser e.ecutado. Essa m(uina virtual dever ser capaz de localizar e carregar as classes
com a aplica'o cliente$ a interface do servi'o e o stub para a implementa'o do servi'o8
+ java CountClient
<e ( para 4(((
+ java CountClient
<e 4((( para F(((
+ java CountReset
+ java CountClient
<e ( para 4(((

Deria possvel tambm ter vrias ativa'-es simult0neas de CountClient em diferentes
m(uinas virtuais Java.
)o caso mais simples de e.ecu'o$ as diversas m(uinas virtuais Java estaro e.ecutando
em uma mesma m(uina$ compartil2ando um C/?##@?8I comum. )o entanto$ 2
mecanismos para permitir o carregamento de classes em uma aplica'o RMI envolvendo
classes remotas.
Ivan Luiz Marques Ricarte
!"#$%%!#&'I!"M(
Iast modified8 ?ue )ov L ##8C#8#L MRD? :BB:

Vous aimerez peut-être aussi