This tutorial is organized as follows:
4.0 Using codebase in RMI for more than just stub downloading
One of the most significant capabilities of the Java platform is the ability to dynamically download Java software from any Uniform Resource Locator (URL) to a Java virtual machine* (JVM) running in a separate process, usually on a different physical system. The result is that a remote system can run a program, for example an applet, which has never been installed on its disk. For the first few sections of this document, codebase with regard to applets will be discussed in order to help describe codebase with regard to Java Remote Method Invocation (RMI).
For example, a JVM running from within a web browser can download the bytecodes for subclasses of java.applet.Applet and any other classes needed by that applet. The system on which the browser is running has most likely never run this applet before, nor installed it on its disk. Once all the necessary classes have been downloaded from the server, the browser can start the execution of the applet program using the local resources of the system on which the client browser is running.
Java RMI takes advantage of this capability to download and execute classes and on systems where those classes have never been installed on disk. Using the RMI API any JVM, not only those in browsers, can download any Java class file including specialized RMI stub classes, which enable the execution of method calls on a remote server using the server system's resources.
The notion of a codebase originates from the use of
A codebase can be defined as a source, or a place, from which to load
classes into a Java virtual machine. For example, if you invited a new
friend over for dinner, you would need to give that friend directions
to the place where you lived, so that he or she could locate your
house. Similarly, you can think of a codebase as the directions that
you give to a JVM, so it can find your [potentially remote]
classes.
You can think of your
To interact with an applet, that applet and any classes that it needs
to run must be accessible by remote clients. While applets can be
accessed from "ftp://" or local
"file:///" URLs, they are usually accessed from
a remote HTTP server.
Figure 1: Downloading applets
The applet's codebase is always relative to the URL of the HTML page in
which the
Using RMI, applications can create remote objects that accept method
calls from clients in other JVMs. In order for a client to call methods
on a remote object, the client must have a way to communicate with the
remote object. Rather than having to program the client to speak the
remote object's protocol, RMI uses special classes called stubs that
can be downloaded to the client that are used to communicate with (make
method calls on) the remote object. The
java.rmi.server.codebase property value represents one or
more URL locations from which these stubs (and any classes needed by
the stubs) can be downloaded.
Like applets, the classes needed to execute remote method calls can be
downloaded from "
Generally, the classes needed to execute remote method calls should be
made accessible from a network resource, such as an HTTP or FTP
server.
Figure 2: Downloading RMI stubs
Figure 3: RMI client making a remote method call
In addition to downloading stubs and their associated classes to
clients, the
When a client makes a method call to a remote object, the method that
it calls could be written to accept no arguments or a number of
arguments. There are three distinct cases that may occur, based on the
data type(s) of the method argument(s).
In the first case, all of the method parameters (and return value) are
primitive data types, so the remote object knows how to interpret them
as method parameters, and there is no need to check its
In the second case, at least one remote method parameter or the return
value is an object, for which the remote object can find the class
definition locally in its
In the third case (shown as Step 6, in Figure 4), the remote method
receives an object instance, for which the remote object cannot find
the class definition locally in its CLASSPATH. This type
of remote method call is illustrated in Figure 4. The class of the
object sent by the client will be a subtype of the declared parameter
type. A subtype is either:
Figure 4: RMI client making a remote method call, passing an unknown
subtype as a method parameter
7. Like the applet's codebase, the client-specified codebase is
used to download
In the case of an applet, the applet codebase value is embedded in an
HTML page, as we saw in the HTML example in the first section of this
tutorial.
In the case of Java RMI codebase, rather than having a reference to the
class embedded in an HTML page, the client first contacts the RMI
registry for a reference to the remote object. Because the remote
object's codebase can refer to any URL, not just one that is relative
to a known URL, the value of the RMI codebase must be an absolute URL
to the location of the stub class and any other classes needed by the
stub class. This value of the codebase property can refer
to:
Note: When the codebase property value is set to
the URL of a directory, the value must be terminated by a
"/".
If the location of your downloadable classes is on an HTTP server named
"webvector", in the directory "export" (under the
web root), your codebase property setting might look like
this:
If the location of your downloadable classes is on an HTTP server named
"webline", in a JAR file named "mystuff.jar", in
the directory "public" (under the web root), your
codebase property setting might look like this:
Now let's suppose that the location of your downloadable classes has
been split between two JAR files, "myStuff.jar" and
"myOtherStuff.jar". If these JAR files are located on
different servers named("webfront" and "webwave"),
your codebase property setting might look like this:
Any serializable class, including RMI stubs, can be downloaded if your RMI programs are configured properly. Here are the conditions under which dynamic stub downloading will work:
and
There are two common problems associated with the
The first problem you might encounter is the receipt of a
It is important to note that the remote object's stub implements all
the same interfaces as the remote object itself, so those interfaces,
as well as any other custom classes declared as method parameters or
return values, must also be available for download from the specified
codebase.
Most frequently, this exception is thrown as a result of omitting the
trailing slash from the URL value of the property. Other reasons would
include: the value of the property is not a URL; the path to the
classes specified in the URL is incorrect or misspelled; the stub class
or any other necessary classes are not all available from the specified
URL.
The exception that you may encounter in such a case would look like this:
The second problem you could encounter is the receipt of a
You may wish to
subscribe to the rmi-users email list.
We are very interested in knowing whether these tutorials are useful.
Please send any comments or suggestions to: rmi-comments@java.sun.com,
with a subject of "codebase tutorial".
*As used on this web site, the terms "Java virtual machine" or "JVM"
mean a virtual machine for the Java platform.
ClassLoaders in the Java programming language. When a Java
program uses a
ClassLoader, that class loader
needs to know the location(s) from which it should be allowed to load
classes. Usually, a class loader is used in conjunction with an HTTP
server that is serving up compiled classes for the Java platform. Most
likely, the first
ClassLoader/codebase
pairing that you came into contact with was the
AppletClassLoader, and the "codebase"
part of the
<applet> HTML tag, so this
tutorial will assume that you have some experience with Java RMI
programming, as well as writing HTML files that contain applet tags.
For example, the HTML source will contain something like:
<applet height=100 width=100 codebase="myclasses/" code="My.class">
<param name="ticker">
</applet>
2.0 What is a codebase?
CLASSPATH as a
"local codebase", because it is the list of places on disk
from which you load local classes. When loading classes from a local
disk-based source, your
CLASSPATH
variable is consulted. Your
CLASSPATH can
be set to take either relative or absolute path names to directories
and/or archives of class files. So just as
CLASSPATH is a kind of "local codebase", the codebase
used by applets and remote objects can be thought of as a "remote
codebase".
3.0 How does it work?
3.1 How codebase is used in applets
CLASSPATH
<applet> tag is contained.
3.2 How codebase is used in RMI
file:///" URLs,
but like applets, a "
file:///" URL
generally requires that the client and the server reside on the same
physical host, unless the file system referred to by the URL is made
available using some other protocol, such as NFS.
CLASSPATH , which is always searched before
the codebase, the client will load the class locally. However,
if the definition for the stub is not found in the client's
CLASSPATH, the client will attempt to retrieve the
class definition from the remote object's codebase.
Note: Steps 4 and 5 are the sames steps that the
registry took to load the remote object class, when the remote
object was bound to a name in (registered with) the RMI
registry. When the registry attempted to load the remote
object's stub class, it requested the class definition from the
codebase associated with that remote object.
4.0 Using codebase in RMI for more than just stub downloading
java.rmi.server.codebase
property can be used to specify a location from which any class, not
only stubs, can be downloaded.
CLASSPATH or any codebase.
CLASSPATH.
Remote classes, non-remote
classes, and interfaces to other JVMs. If the codebase
property is set on the client application, then that codebase is
annotated to the subtype instance when the subtype class is loaded by
the client. If the codebase is not set on the client, the remote object
will mistakenly use its own codebase.
5.0 Command-line examples
Examples
-Djava.rmi.server.codebase=http://webvector/export/
-Djava.rmi.server.codebase=http://webline/public/mystuff.jar
-Djava.rmi.server.codebase="http://webfront/myStuff.jar http://webwave/myOtherStuff.jar"
6.0 Troubleshooting tips
java.rmi.server.codebase property has been
set on the server program (or in the case of activation, the
"setup" program) that makes the call to
bind or
rebind,
such that:
rmiregistry cannot
find the stub class or any of the classes that the stub relies
on in its
CLASSPATH. This is so the
codebase gets annotated to the stub when the registry does its
class load of the stub, as a result of calls to
bind or
rebind in
the server or setup code.
SecurityManager that allows the stub to be
downloaded. In the Java 2 SDK, Standard Edition, v1.2 and later
this means that the client must also have a properly configured
security policy file.
java.rmi.server.codebase property, which are
discussed next.
6.1 If you encounter a problem running your RMI server
ClassNotFoundException when attempting to
bind or
rebind a remote
object to a name in the registry. This exception is usually due to a
malformed
codebase property, resulting in the
registry not being able to locate the remote object's stubs or other
classes needed by the stub.
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: examples.callback.MessageReceiverImpl_Stub
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: examples.callback.MessageReceiverImpl_Stub
java.lang.ClassNotFoundException: examples.callback.MessageReceiverImpl_Stub
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Compiled Code)
at sun.rmi.transport.StreamRemoteCall.executeCall(Compiled Code)
at sun.rmi.server.UnicastRef.invoke(Compiled Code)
at sun.rmi.registry.RegistryImpl_Stub.rebind(Compiled Code)
at java.rmi.Naming.rebind(Compiled Code)
at examples.callback.MessageReceiverImpl.main(Compiled Code)
RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: examples.callback.MessageReceiverImpl_Stub
6.2 If you encounter a problem running your RMI client
ClassNotFoundException when attempting to
lookup a remote object in the registry. If you
receive this exception in a stacktrace resulting from an attempt to run
your RMI client code, then your problem is the
CLASSPATH with which your RMI registry was started.
See requirement C in section 6.0. Here is what
the exception will look like:
java.rmi.UnmarshalException: Return value class not found; nested exception is:
java.lang.ClassNotFoundException: MyImpl_Stub
at sun.rmi.registry.RegistryImpl_Stub.lookup(RegistryImpl_Stub.java:109
at java.rmi.Naming.lookup(Naming.java:60)
at RmiClient.main(MyClient.java:28)
Other resources
If you your codebase questions are still unanswered, please take a look
through the archives of the rmi-users email list first.