CONTENTS | PREV | NEXT | Java Remote Method Invocation |
Activator
Interfaceactivate
method to obtain a
"live" reference to an activatable remote object. Upon
receiving a request for activation, the activator looks up the
activation descriptor for the activation identifier, id,
determines the group in which the object should be activated, and
invokes the newInstance
method on the activation
group's instantiator (the remote interface
ActivationGroup
is described below). The activator
initiates the execution of activation groups as necessary. For
example, if an activation group for a specific group descriptor is
not already executing, the activator will spawn a child JVM for the
activation group to establish the group in the new JVM.
The activator is responsible for monitoring and detecting when activation groups fail so that it can remove stale remote references from its internal tables.
package java.rmi.activation;The
public interface Activator extends java.rmi.Remote { java.rmi.MarshalledObject activate(ActivationID id, boolean force) throws UnknownObjectException, ActivationException, java.rmi.RemoteException; }
activate
method activates the object associated with the activation
identifier, id. If the activator knows the object to be
active already and the force parameter is false,
the stub with a "live" reference is returned immediately to
the caller; otherwise, if the activator does not know that the
corresponding remote object is active or the force
parameter is true
, the activator uses the activation
descriptor information (previously registered to obtain the
id) to determine the group (JVM) in which the object
should be activated. If an ActivationInstantiator
corresponding to the object's group already exists, the
activator invokes the activation instantiator's
newInstance
method, passing it the id and the
object's activation descriptor.
If the activation
instantiator (group) for the object's group descriptor does not
yet exist, the activator starts a new incarnation of an
ActivationInstantiator
executing (by spawning a child
process, for example). When the activator re-creates an
ActivationInstantiator
for a group, it must increment
the group's incarnation number. Note that the incarnation
number is zero-based. The activation system uses incarnation
numbers to detect late ActivationSystem.activeGroup
and ActivationMonitor.inactiveGroup
calls. The
activation system discards calls with an earlier incarnation number
than the current number for the group.
ActivationGroup.createGroup
method. How
the activator sends this information to the spawned process is
unspecified, however, this information could be sent in the form of
marshalled objects to the child process's standard
input.
ActivationSystem.activeGroup
method) specifying the
activation group's reference and incarnation number, the
activator can then invoke that activation instantiator's
newInstance
method to forward each pending activation
request to the activation instantiator and return the result (a
marshalled remote object reference, a stub) to each
caller.
Note that the activator
receives a MarshalledObject
instead of a
Remote
object so that the activator does not need to
load the code for that object, or participate in distributed
garbage collection for that object. If the activator kept a strong
reference to the remote object, the activator would then prevent
the object from being garbage collected under the normal
distributed garbage collection mechanism.
The
activate
method throws
ActivationException
if activation fails. Activation
may fail for a variety of reasons: the class could not be found,
the activation group could not be contacted, etc. The
activate
method throws
UnknownObjectException
if no activation descriptor for
the activation identifier, id, has been previously
registered with this activator. RemoteException
is
thrown if the remote call to the activator fails.
ActivationSystem
InterfaceActivationSystem
provides a means for registering
groups and activatable objects to be activated within
those groups. The ActivationSystem
works closely with
both the Activator
, which activates objects registered
via the ActivationSystem
, and the
ActivationMonitor
, which obtains information about
active and inactive objects and inactive groups.
package java.rmi.activation;
public interface ActivationSystem extends java.rmi.Remote { public static final int SYSTEM_PORT = 1098; ActivationGroupID registerGroup(ActivationGroupDesc desc) throws ActivationException, java.rmi.RemoteException; ActivationMonitor activeGroup(ActivationGroupID id, ActivationInstantiator group, long incarnation) throws UnknownGroupException, ActivationException, java.rmi.RemoteException; void unregisterGroup(ActivationGroupID id) throws ActivationException, UnknownGroupException, java.rmi.RemoteException; ActivationID registerObject(ActivationDesc desc) throws ActivationException, UnknownGroupException, java.rmi.RemoteException; void unregisterObject(ActivationID id) throws ActivationException, UnknownObjectException, java.rmi.RemoteException; void shutdown() throws java.rmi.RemoteException; }
registerGroup
,
activeGroup
, unregisterGroup
,
registerObject
, unregisterObject
, and
shutdown
) will throw
java.rmi.AccessException
, a subclass of
java.rmi.RemoteException,
if called from a client that
does not reside on the same host as the activation system.
registerObject
method is used to register an
activation descriptor, desc, and obtain an activation
identifier for an activatable remote object. The
ActivationSystem
creates an ActivationID
(an activation identifier) for the object specified by the
descriptor, desc, and records, in stable storage, the
activation descriptor and its associated identifier for later use.
When the Activator
receives an activate
request for a specific identifier, it looks up the activation
descriptor (registered previously) for the specified identifier and
uses that information to activate the object. If the group referred
to in desc is not registered with this system, then the
method throws UnknownGroupException
. If registration
fails (e.g., database update failure, etc), then the method throws
ActivationException
. If the remote call fails, then
RemoteException
is thrown.
The
unregisterObject
method removes the activation
identifier, id, and associated descriptor previously
registered with the ActivationSystem
. After the call
completes, the object can no longer be activated via the object's
activation id. If the object id is unknown (not
registered) the method throws UnknownObjectException
.
If the unregister operation fails (e.g., database update failure,
etc.), then the method throws ActivationException
. If
the remote call fails, then RemoteException
is
thrown.
The
registerGroup
method registers the activation group
specified by the group descriptor, desc, with the
activation system and returns the ActivationGroupID
assigned to that group. An activation group must be registered with
the ActivationSystem
before objects can be registered
within that group. If group registration fails, the method throws
ActivationException
. If the remote call fails, then
RemoteException
is thrown.
The
activeGroup
method is a call back from the
ActivationGroup
(with the identifier, id), to
inform the activation system that group is now active and
is the ActivationInstantiator
for that JVM. This call
is made internally by the ActivationGroup.createGroup
method to obtain an ActivationMonitor
that the group
uses to update the system regarding objects' and the
group's status (i.e., that the group or objects within that
group have become inactive). If the group is not registered, then
the method throws UnknownGroupException
. If the group
is already active, then ActivationException
is thrown.
If the remote call to the activation system fails, then
RemoteException
is thrown.
The
unregisterGroup
method removes the activation group
with identifier, id, from the activation system. An
activation group makes this call back to inform the activator that
the group should be destroyed. If this call completes successfully,
objects can no longer be registered or activated within the group.
All information of the group and its associated objects is removed
from the system. The method throws
UnknownGroupException
if the group is not registered.
If the remote call fails, then RemoteException
is
thrown. If the unregister fails, ActivationException
is thrown (e.g., database update failure, etc.).
The
shutdown
method gracefully terminates (asynchronously)
the activation system and all related activation processes
(activator, monitors and groups). All groups spawned by the
activation daemon will be destroyed and the activation daemon will
exit. In order to shut down the activation system daemon,
rmid
, execute the command:
rmid -stop [-port num]This command will shut down the activation daemon on the specified port (if no port is specified, the daemon on the default port will be shut down).
ActivationMonitor
ClassActivationMonitor
is specific to an
ActivationGroup
and is obtained when a group is
reported via a call to ActivationSystem.activeGroup
(this is done internally by the
ActivationGroup.createGroup
method). An activation
group is responsible for informing its
ActivationMonitor
when:
package java.rmi.activation;An activation group calls its monitor's
public interface ActivationMonitor extends java.rmi.Remote { public abstract void inactiveObject(ActivationID id) throws UnknownObjectException, RemoteException; public void activeObject(ActivationID id, java.rmi.MarshalledObject mobj) throws UnknownObjectException, java.rmi.RemoteException; public void inactiveGroup(ActivationGroupID id, long incarnation) throws UnknownGroupException, java.rmi.RemoteException; }
inactiveObject
method when an object
in its group becomes inactive (deactivates). An activation group
discovers that an object (that it participated in activating) in
its JVM is no longer active via a call to the activation
group's inactiveObject
method.
The
inactiveObject
call informs the
ActivationMonitor
that the remote object reference it
holds for the object with the activation identifier, id,
is no longer valid. The monitor considers the reference associated
with id as a stale reference. Since the reference is
considered stale, a subsequent activate
call for the
same activation identifier results in re-activating the remote
object. If the object is not known to the
ActivationMonitor
, the method throws
UnknownObjectException
. If the remote call fails, then
RemoteException
is thrown.
The
activeObject
call informs the
ActivationMonitor
that the object associated with
id is now active. The parameter obj is the
marshalled representation of the object's stub. An
ActivationGroup
must inform its monitor if an object
in its group becomes active by other means than being activated
directly by the system (i.e., the object is registered and
"activated" itself). If the object id is not previously
registered, then the method throws
UnknownObjectException
. If the remote call fails, then
RemoteException
is thrown.
The
inactiveGroup
call informs the monitor that the group
specified by id and incarnation is now inactive.
The group will be re-created with a greater incarnation number upon
a subsequent request to activate an object within the group. A
group becomes inactive when all objects in the group report that
they are inactive. If either the group id is not
registered or the incarnation number is smaller than the current
incarnation for the group, then the method throws
UnknownGroupException
. If the remote call fails, then
RemoteException
is thrown.
ActivationInstantiator
ClassActivationInstantiator
is responsible for creating
instances of activatable objects. A concrete subclass of
ActivationGroup
implements the
newInstance
method to handle creating objects within
the group.
package java.rmi.activation;The activator calls an instantiator's
public interface ActivationInstantiator extends java.rmi.Remote { public MarshalledObject newInstance(ActivationID id, ActivationDesc desc) throws ActivationException, java.rmi.RemoteException; }
newInstance
method in order to
re-create in that group an object with the activation identifier,
id, and descriptor, desc. The instantiator is
responsible for:
getClassName
method,getLocation
method),ActivationID
, and the
MarshalledObject
containing object-specific
initialization data, andMarshalledObject
containing the remote object it
created.inactiveObject
call to its
ActivationMonitor
(see the
ActivationGroup
class for more details).
If object activation
fails, then the newInstance method throws
ActivationException
. If the remote call fails, then
the method throws RemoteException
.
ActivationGroupDesc
ClassActivationGroupDesc
) contains the
information necessary to create or re-create an activation group in
which to activate objects in the same JVM.
null
indicates the default
ActivationGroup
implementation),ActivationGroup
. A subclass of
ActivationGroup
is created or re-created via the
ActivationGroup.createGroup
static method, which
invokes a special constructor that takes two arguments:
package java.rmi.activation;The first constructor creates a group descriptor that uses system default for group implementation and code location. Properties specify Java application environment overrides (which will override system properties in the group implementation's JVM). The command environment can control the exact command/options used in starting the child JVM, or can be
public final class ActivationGroupDesc implements java.io.Serializable { public ActivationGroupDesc(java.util.Properties props, CommandEnvironment env);; public ActivationGroupDesc(String className, String codebase, java.rmi.MarshalledObject data, java.util.Properties props, CommandEnvironment env); public String getClassName(); public String getLocation(); public java.rmi.MarshalledObject getData(); public CommandEnvironment getCommandEnvironment(); public java.util.Properties getPropertiesOverrides(); }
null
to accept
rmid
's default. This constructor will create an
ActivationGroupDesc
with a null
group
class name, which indicates the system's default
ActivationGroup
implementation.
The second constructor
is the same as the first, but allows the specification of
Properties
and CommandEnvironment
.
The
getClassName
method returns the group's class name
(possibly null
). A null
group class name
indicates the system's default ActivationGroup
implementation.
The
getLocation
method returns the codebase path from
where the group's class can be loaded.
The getData
method returns the group's initialization data in marshalled
form.
The
getCommandEnvironment
method returns the command
environment (possibly null
).
The
getPropertiesOverrides
method returns the properties
overrides (possibly null
) for this descriptor.
ActivationGroupDesc.CommandEnvironment
ClassCommandEnvironment
class allows overriding default
system properties and specifying implemention-defined options for
an ActivationGroup
.
public static class CommandEnvironment implements java.io.Serializable { public CommandEnvironment(String cmdpath, String[] args); public boolean equals(java.lang.Object); public String[] getCommandOptions(); public String getCommandPath(); public int hashCode(); }The constructor creates a
CommandEnvironment
with the given command,
cmdpath, and additional command line options,
args.
The equals
implements content equality for command environment objects. The
hashCode
method is implemented appropriately so that a
CommandEnvironment
can be stored in a hash table if
necessary.
The
getCommandOptions
method returns the environment
object's command line options.
The
getCommandPath
method returns the environment
object's command string.
ActivationGroupID
ClassActivationGroupID
is returned from the call to
ActivationSystem.registerGroup
and is used to identify
the group within the activation system. This group identifier is
passed as one of the arguments to the activation group's
special constructor when an activation group is created or
re-created.
package java.rmi.activation;The
public class ActivationGroupID implements java.io.Serializable { public ActivationGroupID(ActivationSystem system); public ActivationSystem getSystem(); public boolean equals(Object obj); public int hashCode(); }
ActivationGroupID
constructor creates a unique group
identifier whose ActivationSystem is system.
The
getSystem
method returns the activation system for the
group.
The
hashCode
method returns a hashcode for the group's
identifier. Two group identifiers that refer to the same remote
group will have the same hash code.
The equals
method compares two group identifiers for content equality. The
method returns true
if both of the following
conditions are true: 1) the unique identifiers are equivalent (by
content), and 2) the activation system specified in each refers to
the same remote object.
ActivationGroup
ClassActivationGroup
is responsible for creating new
instances of activatable objects in its group, informing its
ActivationMonitor
when:
ActivationGroup
is initially created in one
of several ways:
ActivationDesc
for an
object, orActivationGroup.createGroup
method, orActivationGroupDesc
was only registered.ActivationGroup
. The activator
spawns, as needed, a separate JVM (as a child process, for example)
for each registered activation group and directs activation
requests to the appropriate group. It is implementation specific
how JVMs are spawned. An activation group is created via the
ActivationGroup.createGroup
static method. The
createGroup
method has two requirements on the group
to be created: 1) the group must be a concrete subclass of
ActivationGroup
, and 2) the group must have a
constructor that takes two arguments:
When created, the default
implementation of ActivationGroup
will set the system
properties to the system properties in force when the
ActivationGroupDesc
was created, and will set the
security manager to the java.rmi.RMISecurityManager
.
If your application requires some specific properties to be set
when objects are activated in the group, the application should set
the properties before creating any ActivationDesc
s
(before the default ActivationGroupDesc
is created).
package java.rmi.activation;The activator calls an activation group's
public abstract class ActivationGroup extends UnicastRemoteObject implements ActivationInstantiator { protected ActivationGroup(ActivationGroupID groupID) throws java.rmi.RemoteException; public abstract MarshalledObject newInstance(ActivationID id, ActivationDesc desc) throws ActivationException, java.rmi.RemoteException; public abstract boolean inactiveObject(ActivationID id) throws ActivationException, UnknownObjectException, java.rmi.RemoteException; public static ActivationGroup createGroup(ActivationGroupID id, ActivationGroupDesc desc, long incarnation) throws ActivationException; public static ActivationGroupID currentGroupID(); public static void setSystem(ActivationSystem system) throws ActivationException; public static ActivationSystem getSystem() throws ActivationException; protected void activeObject(ActivationID id, java.rmi.MarshalledObject mobj) throws ActivationException, UnknownObjectException, java.rmi.RemoteException; protected void inactiveGroup() throws UnknownGroupException, java.rmi.RemoteException; }
newInstance
method in order to
activate an object with the activation descriptor, desc.
The activation group is responsible for:
getClassName
method,getLocation
method),ActivationID
, and a MarshalledObject
containing the object's initialization data, andActivationException
if the instance for the given
descriptor could not be created.
The group's
inactiveObject
method is called indirectly via a call
to the Activatable.inactive
method. A remote object
implementation must call Activatable
's
inactive
method when that object deactivates (the
object deems that it is no longer active). If the object does not
call Activatable.inactive
when it deactivates, the
object will never be garbage collected since the group keeps strong
references to the objects it creates.
The group's
inactiveObject
method unexports the remote object,
associated with id (only if there are no pending or
executing calls to the remote object) from the RMI runtime so that
the object can no longer receive incoming RMI calls. If the object
currently has pending or executing calls,
inactiveObject
returns false
and no
action is taken.
If the
unexportObject
operation was successful (meaning that
the object has no pending or executing calls), the group informs
its ActivationMonitor
(via the monitor's
inactiveObject
method) that the remote object is not
currently active so that the remote object will be reactivated by
the activator upon a subsequent activation request. If the
operation was successful, inactiveObject
returns
true
. The operation may still succeed if the object is
considered active by the ActivationGroup
but has
already been unexported.
The
inactiveObject
method throws an
UnknownObjectException
if the activation group has no
knowledge of this object (e.g., the object was previously reported
as inactive, or the object was never activated via the activation
group). If the inactive operation fails (e.g., if the remote call
to the activator or activation group fails),
RemoteException
is thrown.
The
createGroup
method creates and sets the activation
group for the current JVM. The activation group can only be set if
it is not currently set. An activation group is set using the
createGroup
method when the Activator
initiates the re-creation of an activation group in order to carry
out incoming activate
requests. A group must first
register a group descriptor with the ActivationSystem
before it can be created via this method (passing it the
ActivationID
obtained from previous registration).
The group specified by
the ActivationGroupDesc
, desc, must be a
concrete subclass of ActivationGroup
and have a public
constructor that takes two arguments; the
ActivationGroupID
for the group and a
MarshalledObject
containing the group's
initialization data (obtained from its
ActivationGroupDesc
). If the
ActivationGroupDesc.getClassName
method returns
null
, the system's default group implementation is
used. Note: if your application creates its own custom activation
group, the group must set a security manager in the constructor, or
objects cannot be activated in the group.
After the group is
created, the ActivationSystem
is informed that the
group is active by calling the activeGroup
method,
which returns the ActivationMonitor
for the group. The
application need not call activeGroup
independently
since that callback is taken care of by the
createGroup
method.
Once a group is created,
subsequent calls to the currentGroupID
method will
return the identifier for this group until the group becomes
inactive, at which point the currentGroupID
method
will return null
.
The parameter
incarnation indicates the current group incarnation, i.e.,
the number of times the group has been activated. The incarnation
number is used as a parameter to the activeGroup
method, once the group has been successfully created. The
incarnation number is zero-based. If the group already exists, or
if an error occurs during group creation, the
createGroup
method throws
ActivationException
.
The
setSystem
method sets the
ActivationSystem
, system, for the JVM. The
activation system can only be set if no group is currently active.
If the activation system is not set via an explicit call to
setSystem
, then the getSystem
method will
attempt to obtain a reference to the ActivationSystem
by looking up the name
java.rmi.activation.ActivationSystem in the
Activator's registry. By default, the port number used to look
up the activation system is defined by
ActivationSystem.SYSTEM_PORT. This port can be overridden
by setting the property java.rmi.activation.port. If the
activation system is already set when setSystem
is
called, the method throws ActivationException
.
The
getSystem
method returns the activation system for the
JVM. The activation system may be set by the setSystem
method (described above).
The
activeObject
method is a protected method used by
subclasses to make the activeObject
call back to the
group's monitor to inform the monitor that the remote object
with the specified activation id and whose stub is
contained in mobj is now active. The call is simply
forwarded to the group's ActivationMonitor
.
The
inactiveGroup
method is a protected method used by
subclasses to inform the group's monitor that the group has
become inactive. A subclass makes this call when each object the
group participated in activating in the JVM has become
inactive.
MarshalledObject
ClassMarshalledObject
is a container for an object that
allows that object to be passed as a parameter in an RMI call, but
postpones deserializing the object at the receiver until the
application explicitly requests the object (via a call to the
container object). The Serializable
object contained
in the MarshalledObject
is serialized and deserialized
(when requested) with the same semantics as parameters passed in
RMI calls, which means that any remote object in the
MarshalledObject
is represented by a serialized
instance of its stub. The object contained by the
MarshalledObject
may be a remote object, a non-remote
object, or an entire graph of remote and non-remote objects.
When an object is placed
inside the MarshalledObject
wrapper, the serialized
form of the object is annotated with the codebase URL (where the
class can be loaded); likewise, when the contained object is
retrieved from its MarshalledObject
wrapper, if the
code for the object is not available locally, the URL (annotated
during serialization) is used to locate and load the bytecodes for
the object's class.
package java.rmi;
public final class MarshalledObject implements java.io.Serializable { public MarshalledObject(Object obj) throws java.io.IOException; public Object get() throws java.io.IOException, ClassNotFoundException; public int hashCode(); public boolean equals(); }
MarshalledObject
's constructor takes a
serializable object, obj, as its single argument and holds
the marshalled representation of the object in a byte stream. The
marshalled representation of the object preserves the semantics of
objects that are passed in RMI calls:
get
method), the
bytecodes for each class can be located and loaded, andMarshalledObject
is written to a
java.io.ObjectOutputStream
, the contained object's
marshalled form (created during construction) is written to the
stream; thus, only the byte stream is serialized.
When a
MarshalledObject
is read from a
java.io.ObjectInputStream
, the contained object is not
deserialized into a concrete object; the object remains in its
marshalled representation until the marshalled object's
get
method is called.
The get
method always reconstructs a new copy of the contained object from
its marshalled form. The internal representation is deserialized
with the semantics used for unmarshalling parameters for RMI calls.
So, the deserialization of the object's representation loads
class code (if not available locally) using the URL annotation
embedded in the serialized stream for the object.
The
hashCode
of the marshalled representation of the
object is the same as the object passed to the constructor. The
equals
method will return true if the marshalled
representation of the objects being compared are equivalent. The
comparison that equals uses ignores a class's codebase
annotation, meaning that two objects are equivalent if they have
the same serialized representation except for the codebase
of each class in the serialized representation.