Title: Advanced%20RMI
1Lesson 3
2Assorted real-world RMI issues
3Review of rmi basics
- rmi is a relatively very simple D.O. framework.
- Major limitations
- Only java to java
- Major advantages
- Clean, easy to deploy, robust
- Maps very cleanly to java language semantics
- Competing frameworks/technologies
- CORBA
- Web Services
4rmi approach
- Distributed objects have look-and-feel of local
objects, but can be called across machines. - A distributed object is a regular object
augmented with the following - Extends UnicastRemoteObject
- Have public distributed methods that throw
RemoteException - Have parameters that implement Serializable
- Have a constructor that throws RemoteException
(it need not directly call super) - Have a separate interface file that lists the
remote methods and extents java.rmi.Remote.
5Todays naming convention for rmi
Naming convention Example File type
No Suffix Foo Remote interface
Impl Suffix FooImpl Business Logic
Server suffix FooServer Program that creates objs
Client Suffix FooClient Client program
6Creating stubs
- Layout of most simple rmi application before stub
generation looks like - Server
- StoreImpl.java (implementation)
- Store.java (interface)
- StoreServer.java (to bootstrap)
- Other local classes
- Client
- StoreClient.java
- Store.java
- Must compile client and server before using rmic!
7Stub Class Generation
- Recall that the _stub class contains the glue
messaging code on both the client and the server. - There are three ways to create the stubs
depending on which version of java you are using - As of jdk5.0, stubs generated automatically.
- As of jdk1.2, stubs are generated as
- rmic v1.2 StoreImpl
- Before jdk1.2, stubs and skeletons are creates as
- rmic v1.1 StoreImpl
- This creates StoreImpl_stub.class
8Creating stubs
- Layout of most simple rmi application before stub
generation looks like - Server
- StoreImpl.class (implementation)
- Store.class (interface)
- StoreServer.class (to bootstrap)
- Other local classes
- StoreImpl_stub.class
- Client
- StoreClient.class
- Store.class
- StoreImpl_stub.class
- Must compile client and server before using rmic!
Make sure these are same!
9Deployment issues
- A couple of more sophisticated issues arise in
deployment - How to have client automatically download stubs
and update class defintions - How to handle security issues
- There are pretty simple approaches for each
described in book. - For now, we will assume in our assignments that
client has all updated class files and that
security is not an issue. - I will give a quick pointer to security issues
later in this lecture.
10More complex issues
11Typical model of callback
class Client Client() Server x new
Server() x.doIt(, this) doIt()
. class Foo public void doIt(,
Client client) client.doIt()
12Callback example timer class
- At specified time interval, server sends you e.g.
current time, which you display locally. - Design
- Server contains register method and receives
remote reference to client - Client contains update method which recieves
current time and displays - Consider how both all rmi and rmi sockets
version of this program would look
13Another callback example
- TicTacToe game is another good example of a
callback. - Client accesses server object to place next move.
- Once new move is placed and accepted, server must
contact other player with updated move. - In this sense, server become client and client
server for this particular call - How to architect this with rmi?
14Tic-tac-toe with RMI
- Pure rmi implementation
- TicTacToeClient is adorned as D.O. also!
- Contains method such as otherPlayerMove
- TicTacToeClient calls server register method and
passes copy of this - TicTacToeImpl stores this and uses for D.O. call
to inform other player of current players move. - Note that notion of server and client is only
meaningful for a particular method!
15Tic-tac-toe with RMI
- RMI sockets implementation
- In this example, each client runs a socket server
and gets a direct socket connection from the game
server - TicTacToeClient is not a remote object
- Game server still runs as remote object in
regular way - Examples all posted on web site
16Handling many server objects
17Binding many objects to registry
- What if many people logon to play tic-tac-toe?
How do we give each pair their own game? - What if we have many objects in general to post?
- There are two ways to deal with this
- give each their own name in registry (not good)
- bootstrap off a single factory method (good)
18Bootstrapping
- For tic-tac-toe example, we could have a method
-
- TicTacToe getGame() throws RemoteException
- As long as both getGame and TicTacToeImpl are
setup up as remote, only one remote object need
get posted to the registry. - Can create a pool of tic-tac-toe games and assign
as they come in. - Will be required for hw2, recommended for hw1.
- This is a great simplification vs. binding
multiple objects! - See examples under bootstrap directory
19Contacting rmi registry
- In our simplified application, to get a remote
reference we called - Naming.lookup(tic-tac-toe)
- This assumes the default rmi port (1099) on
localhost. - To change ports, run rmiregistery ltportgt
- The more general rmi URL is
- Naming.lookup(rmi//hostport/name)
- e.g. to lookup on port 99 at host yourserver.com
- Naming.lookup(rmi//yourserver.com99/tic-tac-t
oe)
20Listing objects in the registery
- Note that the Naming class has a method list
which returns a listing of all objects bound to
the registry. - It is called from the client as
- String bindings Naming.list(ltrmi url goes
heregt)
21Other changes in jdk5.0
22Naming service
23Security issues
- Recall that client needs up-to-date stub
functions. - No problem if these are available locally on
client. - However, keeping a local installation can be
cumbersome. Often stubs are downloaded via other
servers (well see how to do this). - In this case, a SecurityManager needs to be
installed to ensure that the stubs are not
hostile (unless applet is used, which has its own
SecurityManager).
24A few notes about security/deployment
25RMISecurityManager
- Easiest way to do this
- System.setSecurityManager(new
RMISecurityManager()) - By default prohibits any socket connections
- Obviously this is too strict. Need a policy file
to allow client to make network connection to rmi
port. It would look something like - grant permission java.net.SocketPermission
- 1024-65535, connect
- java Client Djava.security.policyclient.policy
26Server-side security/firewalls
- For this class we assume you have control over
the server security configuration.
27RMI application deployment
- Very simple if client/server both have up-to-date
copies of all class files - However, this is unrealistic and impractical.
- Better if client can dynamically load classes
remotely. - RMI provides such a mechanism built on top of
standard server protocols
28Deployment, cont.
- For server, following classes must be available
to its classloader - Remote service interface definitions
- Remote service implementations
- Stubs
- All other server classes
- For client
- Remote service interface definitions
- Stubs
- Server classes for objects used by the client
(e.g. return values) - All other client classes
29RMIClassLoader
- RMI support remote class loading by specfying the
java.rmi.server.codebase property with an
appropriate URL - This is done as
- java WhateverImp
- -Djava.rmi.server.codebasehttp//whatever
- ftp, file, etc. can also be used
- See deployment directory in class examples
- Proper remote deployment will be required on the
next assignment.
30Remote Objects and object methods
31Using Remote Objects in Sets
- Recall that equals() and hashcode must be
overridden to use Sets. - For remote objects, this would require a network
call to the server, which could fail. - Since equals does not throw RemoteException, it
cannot be overridden and used remotely. - Thus, must use equals and hashCode methods in
RemoteObject class. - These unfortunately only compare stubs, not
contents. - Probably not a great idea to do this unless
necessary
32clone() method
- Can not call at all directly for stubs
- If you want to clone, simply define a new remote
method (e.g. remoteClone), have it call clone
locally, and return copy as parameter.
33Non-remote objects
- Note that all objects which are not remote are
fully copied to client - This is very different from local method call,
where objects are passed as references. - Thus, only remote objects can change state across
client-server call - Also, performance issues can arise for very deep
object graphs
34Remote Objects and Inheritance
35Using inheritance with rmi
- Stubs are generated only from classes that
implement a remote interface (and only for
methods in that interface). - Subclasses of remote classes can be defined and
used in place of superclass in remote method
call. - However, only superclass remote methods will be
available, not any other defined in subclass!
36Synchronized RMI calls
37Using synchronized methods in rmi
- Recall that remote objects are passed by
reference (stub). - Thus, when many users request the same object,
they are manipulating a single copy. - If the object is immutable, there is no need to
synchronize. - Otherwise, proper synchronization should be done
in the regular way using synchronized methods
where appropriate, and synchronized blocks if
necessary.
38RMI calling semantics
39Native Data Types
- Native data types
- pass by value parameter copied before remote
transmission - exactly like single jvm behavior
- machine-independent format used
40Objects
- Calling sequence for object parameters
- pass by value also!
- this differs from single-jvm behavior
- All objects are completely serialized (deep copy)
and sent to remote location. - This can be hugely inefficient. Be very careful
when performance is at a premium!
41Remote Objects
- Java defines a third type of parameter a remote
object. - Remote objects must be setup as rmi distributed
objects in the regular way (extend
UnicastRemoteObject and implement Remote
interface) - Remote objects are pass-by-reference. proxies
rather than serialized objects are returned.
42Distributed Garbage Collection
43Distributed garbage collection
- Server keeps track of clients that have requested
object. - When client disconnects, they are removed from
the list. - Also a timeout mechanism controlled by
java.rmi.dgc.leaveValue. - Remote object can implement java.rmi.server.Unfere
renced to get notification when clients no longer
hold live reference. - Bottom line not much to worry about here.
44Object Activation
45Creating objects remotely
- What we have learned about RMI requires the
server to instantiate one or more objects and
post them to the registry - What if objects do not exists. Is it possible for
the client to remotely create an object on the
server? - This can be useful occasionally and is now
possible with java Activation framework. - We will not discuss Activation in this class.
46RMI inter-language calls indirectly using JNI
47JNI
- Recall that CORBA allows inter-language remote
object calls RMI does not! - However, JNI allows one to call native code
directly from java. - Thus, the two together give more CORBA-like
capabilities. - rmi calls java remote method, which locally calls
C code, which returns java parameter(s), and rmi
sends back to client.
48What exactly does JNI do?
- Provides the glue between java C/C (but no
other languages) - Provides the machinery for mapping datatypes.
- Can be used to call C/C from Java (typical), or
Java from C (invocation API) - Does NOT provide network transparency!
49Reasons for using JNI
- Feature not available in java language.
- Code already written in another language, dont
want to rewrite. - Java is slow.
- Other language has no additional features per se,
but has much better syntax for handling certain
operations (Fortran for math).
50Problems with JNI
- Only provides C/C bindings. Going to Fortran,
COBOL, Ada, etc. requires extra step. - Not portable
- Mapping is not trivial
- No built-in security
51Basic steps to calling native code
- Write java class with a method declared with
native keyword. Provide no implementation - public native void sayHello()
- Example above is most simple, but method may pass
any parameters or have any return type. - Add a call to System.loadLibrary(libname) in
the class that declares the native method - static
- System.loadLibrary(hello)//static means
called only once.
52Steps, cont.
- 3. Compile the class
- javac Hello.java
- 4. Produce the C/C header files using the
javah utility - javah Hello
- This produces the header file Hello.h
- Write your implementation file by first copying
the function signature produced in the include
file. Also, include the header file. - include Hello.h
53Steps, cont.
- 6. Write the implementation in C/C. This will
require using JNI methods to access the data or
possibly casts to convert to basic C/C types - 7. Best technique Break into two steps. Think
of your C/C function as a wrapper which
accesses the Java data and maps it to C data
using JNI methods, then shoves the converted data
into a prewritten standalone C program.
54Steps, cont.
- 8. Compile your native method(s) as a shared
object (or DLL on Windows). - WARNING Be sure to point your linker to the
include files in /jdk1.3/include and
jdk1.3/include/linux (for example). - WARNING Mixing languages is much easier using a
straight C wrapper rather than C. - 9. Set the environment variable LD_LIBRARY_PATH
to the shared object directory - Run main Java class.
55Mapping of datatypes
- C datatypes are platform-dependent. Those in java
arent. - Thus, JNI defines its own portable C datatypes.
- See next slide for mapping of native types.
56Native java/c data mappings
Java C Bytes
boolean jboolean 1
byte jbyte 1
char jchar 2
short jshort 2
int jint 4
long jlong 8
float jfloat 4
double jdouble 8
57String mappings
- Java and C strings are very different (Unicode
vs. 8-bit null terminated). - Thus, JNI cannot simply pass memory from java to
C. - Some mapping must occur.
- This is handled via C utility functions provided
with JNI. - jstring is opaque type, and methods operate
directly on/create jstring types.
58What does Java pass to my C function?
- How are these utility functions provided?
- JNIEnv A pointer to the the JNI environment.
This pointer is a handle to the current thread in
the JVM, and contains mapping functions and other
housekeeping information. - jobject A reference to the object that called
the native code (this) for non-static methods - or
- jclass A descriptor of the class which contains
the method for static methods - Any arguments specified by the method.
59String functions
- The string functions look like this
- jstring NewStringUTF(JNIEnv, const char)
- jsize GetStringUTFLength(JNIEnv, jstring)
- void REleaseStringUTFChars(JNIEnv, jstring,
const jbyte) - void ReleaseStringChars(JNIEnv, jstring, const
jchar) - etc.
- etc.
60Modifying object fields
- What if we want to go beyond number and string
parameters? - One such case is a method that manipulates object
state - It is cumbersome but but not conceptually
difficult to write native methods that manipulate
object state.
61Test case Employee class
- Imagine the following simple Employee class
- public class Employee
- public void raiseSalary(double percent)
- this.salary 1 percent / 100
-
- private double salary
-
- We want to write this as a native method
62Making raiseSalary native
- To make raiseSalary native, we hit the signature
with javah and get the following - JNIEXPORT void JNICALL Java_Employee_raiseSalary
(JNIEnv, jobject, jdouble) - Note that second argument is of type jobject
since method is non-static. It is like this. - We need to access, change, and set the salary
field of the implicit parameter. - This is a several step process.
63How to access the fields of implicit parameter
- General syntax is
- x (env)-gtGetXxxField(env, class, fieldID)
- To get the object class
- jclass class_Employee (env)-gtGetObjectClass
(env, obj_this) - To get the fieldID, do
- jfieldID id_salary (env)-gtGetFieldID(env,class_
Employee, salary, D) - (string D denotes the type double)
- Finally, call SetXxxField to affect change.
64Source code for example
JNIEXPORT void JNICALL Java_Employee_raiseSalary(
JNIEnv env, jobject obj_this, jdouble
byPercent) jclass class_Employee
(env)-gtGetObjectClass(env, obj_this) jfieldID
id_salary (env)-gtGetFieldID(env,
class_Employee, salary, D) jdouble
salary (env)-gtGetDoubleField(env, obj_this,
id_salary) salary 1 byPercent / 100
(env)-gtSetDoubleField(env, obj_this, id_salary,
salary)
65Manipulating static fields
- Similar to object fields, but must get class
using a different method, e.g. to access the
static out object in the System class - jclass class_System (env)-gtFindClass(env,
java/lang/System) - To get the fieldID
- jfieldID id_out (env)-gtGetStaticFieldID(env,
class_System, out, Ljava/io/PrintStream - To get static object field
- jobject obj_out (env)-gtGetStaticObjectFie
ld(env, class_System, id_out)
66Callbacks on java methods
- This is possible and quite straightforward as
well. - Simple use (env)-gtCallXxxMethod(env, implicit
parameter, methodID, explicit parameters). - Xxx can be Void, Int, Object, etc. depending on
return type of method. - MethodID is like fieldID use GetMethodID
function - Note that GetMethodID requires class name, method
name, AND signature. How to specify signature is
detailed in Horstmann ch 11.
67Encoding scheme for method signatures in JNI
B byte
C char
D double
F float
I int
J long
Lclassname a class type
S short
V void
Z boolean
68More on signatures
- Example
- Employee(java.lang.String double
java.util.Date) - has signature encoding
- (Ljava/lang/StringDLjava/util/Date)V
- Note that String is wrapped in parentheses, there
is no separator between types (other than for
class types), and return type is appended). - What does (II)I describe?
- What does (Ljava/lang/String)V describe?
- Note Arrays of any type simply begin with
- What does (II)I describe?
69javap tool
- Java contains a tool called javap that can be run
on a class file to produce the field signatures.
e.g. - javap s private Classname
- This is fun and useful to play with to learn/save
time.
70Static Methods
- Calling static methods is similar to object
methods. - There are two differences
- Use GetStaticMethodID and CallStaticXxxMethod
- Supply class object rather than implicit
parameter object.
71Arrays
- Arrays in java are mapped as opaque C types Here
are a few others obvious
Java type C type
boolean jbooleanArray
int jintArray
double jdoubleArray
Object jobjectArray
72Some Array methods
- jsize GetArrayLength(JNIEnv, jarray)
- jobject GetObjectArrayElement(JNIEnv,
jobjectArray, jsize) - void SetObjectArrayElement(JNIEnv, jobjectArray,
jsize, jobject) - Xxx GetXxxArrayElements(JNIEnv, jarray,
jboolean isCopy) - void ReleaseXxxArrayElements(JNIEnv, jarray, Xxx
elems, jint mode) - etc.
- etc.
73Examples on union
- HelloWorld Example No data passed
- Hello.java
- Hello.cc
- Max example Only native dataypes
- Utils.java
- utils.cc
- Advanced Max example Arrays
- Utils.java
- utils.cc
- Max Java-C-Fortran max.f
74A simple alternative spawning a system
executable
- Advantages
- Infinitely simpler
- Portable
- Can use any native language
- Disadvantages
- Can only pass data to and from vi stdout
- Must reload executable for each invocation
75Spawning Executable -- technique
- Process p Runtime.exec(some_exec)
- Use p to manage process
- p.getInputStream()
- p.getOutputStream()
- p.kill()
- p.halt()
76Other topics
- Invocation API (C calls java directly).
- Calling constructors from native code
- throwing java exceptions