Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

76
Lesson 3 Advanced RMI JNI

Transcript of Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Page 1: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Lesson 3

Advanced RMI

JNI

Page 2: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Assorted real-world RMI issues

Page 3: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Review 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

Page 4: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

rmi 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.

Page 5: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Today’s naming convention for rmi

Naming convention

Example File type

No Suffix FooRemote interface

Impl Suffix FooImpl“Business Logic”

Server suffix

FooServerProgram that creates objs

Client Suffix

FooClientClient program

Page 6: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Creating 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!

Page 7: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Stub 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

Page 8: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Creating 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!

Page 9: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Deployment 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.

Page 10: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

More complex issues

Callbacks

Page 11: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Typical model of callbackclass Client{ Client(){ Server x = new Server(); x.doIt(…, this); } doIt(…){ …. }}

class Foo{ public void doIt(…, Client client){

… client.doIt();

}}

Page 12: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Callback 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

Page 13: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Another 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?

Page 14: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Tic-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!

Page 15: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Tic-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

Page 16: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Handling many server objects

Bootstrapping registry

Page 17: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Binding 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)

Page 18: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Bootstrapping 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

Page 19: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Contacting 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 <port> The more general rmi URL is

Naming.lookup(“rmi://host:port/name”);

e.g. to lookup on port 99 at host yourserver.com

Naming.lookup(“rmi://yourserver.com:99/tic-tac-toe”);

Page 20: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Listing 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(“<rmi url goes here>”);

Page 21: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Other changes in jdk5.0

Page 22: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Naming service

Page 23: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Security 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 (we’ll 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).

Page 24: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

A few notes about security/deployment

Page 25: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

RMISecurityManager 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.policy=client.policy

Page 26: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Server-side security/firewalls

For this class we assume you have control over the server security configuration.

Page 27: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

RMI 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

Page 28: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Deployment, 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

Page 29: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

RMIClassLoader

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.codebase=http://whatever

ftp, file, etc. can also be used See deployment directory in class examples

Proper remote deployment will be required on the next assignment.

Page 30: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Remote Objects and object methods

Clone, equals, etc.

Page 31: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Using 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

Page 32: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

clone() 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.

Page 33: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Non-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

Page 34: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Remote Objects and Inheritance

Page 35: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Using 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!

Page 36: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Synchronized RMI calls

Page 37: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Using 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.

Page 38: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

RMI calling semantics

Page 39: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Native Data Types

Native data types– pass by value – parameter copied before remote

transmission– exactly like single jvm behavior– machine-independent format used

Page 40: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Objects

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!

Page 41: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Remote 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.

Page 42: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Distributed Garbage Collection

Page 43: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Distributed 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.Unfererenced to get notification when clients no longer hold live reference.

Bottom line: not much to worry about here.

Page 44: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Object Activation

Page 45: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Creating 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.

Page 46: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

RMI inter-language calls indirectly using JNI

Page 47: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

JNI

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.

Page 48: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

What 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!

Page 49: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Reasons for using JNI

Feature not available in java language. Code already written in another language,

don’t 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).

Page 50: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Problems 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

Page 51: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Basic steps to calling native code

1. 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.

2. Add a call to System.loadLibrary(“libname”) in the class that declares the native method:

– static{System.loadLibrary(“hello”);}//static means called only once.

Page 52: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Steps, 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

5. Write your implementation file by first copying the function signature produced in the include file. Also, #include the header file.

#include “Hello.h”

Page 53: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Steps, 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.

Page 54: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Steps, 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.

Page 55: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Mapping of datatypes

C datatypes are platform-dependent. Those in java aren’t.

Thus, JNI defines its own portable C datatypes.

See next slide for mapping of native types.

Page 56: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Native 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

Page 57: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

String 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.

Page 58: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

What 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– orjclass: A descriptor of the class which contains the

method for static methods Any arguments specified by the method.

Page 59: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

String 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.

Page 60: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Modifying 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.

Page 61: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Test 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

Page 62: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Making 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.

Page 63: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

How to access the fields of implicit parameter General syntax is:

x = (*env)->GetXxxField(env, class, fieldID);

To get the object class: jclass class_Employee = (*env)->GetObjectClass(env, obj_this);

To get the fieldID, do:jfieldID id_salary = (*env)->GetFieldID(env,class_Employee,

“salary”, “D”);

(string D denotes the type – double)

Finally, call SetXxxField to affect change.

Page 64: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Source code for example

JNIEXPORT void JNICALL Java_Employee_raiseSalary( JNIEnv* env, jobject obj_this, jdouble byPercent){

jclass class_Employee = (*env)->GetObjectClass(env, obj_this); jfieldID id_salary = (*env)->GetFieldID(env, class_Employee, “salary”, “D”); jdouble salary = (*env)->GetDoubleField(env, obj_this, id_salary);

salary *= 1 + byPercent / 100;

(*env)->SetDoubleField(env, obj_this, id_salary, salary);

}

Page 65: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Manipulating 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)->FindClass(env, “java/lang/System”);

To get the fieldIDjfieldID id_out = (*env)->GetStaticFieldID(env, class_System, “out”,

“Ljava/io/PrintStream;”

To get static object field jobject obj_out = (*env)->GetStaticObjectField(env, class_System,

id_out);

Page 66: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Callbacks on java methods This is possible and quite straightforward as well.

Simple use (*env)->CallXxxMethod(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.

Page 67: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Encoding 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

Page 68: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

More on signatures Example:

– Employee(java.lang.String; double; java.util.Date)has signature encoding:“(Ljava/lang/String;DLjava/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 ([I[I)I describe?

Page 69: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

javap 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.

Page 70: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Static 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.

Page 71: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Arrays

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

Page 72: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Some Array methodsjsize 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.

Page 73: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Examples 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

Page 74: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

A 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

Page 75: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Spawning Executable -- technique Process p = Runtime.exec(“some_exec”); Use p to manage process:

– p.getInputStream();– p.getOutputStream();– p.kill();– p.halt();

Page 76: Lesson 3 Advanced RMI JNI. Assorted real-world RMI issues.

Other topics

Invocation API (C calls java directly). Calling constructors from native code throwing java exceptions