Upload
hoanganh
View
219
Download
5
Embed Size (px)
Citation preview
SUB CODE:IT0407
SUB NAME:INTEGRATIVE PROGRAMMING & TECHNOLOGIES
SEM : VII
112/26/2012
N.J.Subashini
Assistant Professor,(Sr. G)
SRM University, Kattankulathur
312/26/2012
UNIT 1 LANGUAGE INTEROPERABILITY INJAVA 9
Using non-Java code: The Java Native Interface- Calling a native method -Implementing your DLL- Accessing JNI functions - Passing and usingJava objects - JNI and Java exceptions-JNI andthreading
512/26/2012
to access the non java codes different vendors provides different solutions
Java 1.1 has the Java Native Interface (JNI)Netscape has proposed its Java Runtime InterfaceMicrosoft offers J/Direct, Raw Native Interface
(RNI), and Java/COM integration.Another Solution is CORBA((Common Object
Request Broker Architecture), an integration technology developed by the OMG (Object Management Group) –interoperable with objects – no language specific –provides common communication bus and services called ORB(Object Request Broker)
712/26/2012
JNI is a fairly rich programming interface that allow to call native methods from a Java application.
It was added in Java 1.1, maintaining a certain degree of compatibility with its Java 1.0 equivalent, the native method interface (NMI).
NMI has design characteristics that make it unsuitable for adoption in all virtual machines.
For this reason, future versions of the language might no longer support NMI.
812/26/2012
JNI is designed to interface with native methods written only in C or C++.
Using JNI, native methods can:Create, inspect, and update Java objects (including
arrays and Strings)Call Java methodsCatch and throw exceptionsLoad classes and obtain class informationPerform runtime type checking
Thus, virtually everything which can be done with classes and objects in ordinary Java can also be done in native methods.
912/26/2012
Steps for creating a JNI Program:-1. Create a java file with a ‘native ‘ methods2. Create header file for the java file3. Create C file using the header file
generated for the java file, which have the native method structure
4. Create .dll file5. Execute the program
1112/26/2012
Create a java file with a ‘native ‘ methods:-Create a new project called as JniDemo, don’t remove the check boxes in ita project with a subpackage called jnidemo and a class called Main will be opened.now include the following code in it
1212/26/2012
package jnidemo;
public class Main {
private native static void nativePrint();public native static int intMethod(int n);
public static void main(String[] args) {nativePrint();System.out.println("Sum=="+ intMethod(10));
}}
Compile and build
1312/26/2012
Create header file for the java fileTo create the .h file for the java file use the following commandE:\Programs\Jnidemo\src\jnidemo>"C:\Program Files\Java\jdk1.6.0_07\bin\javah.exe" -o HelloWorldNaive.h -jni -classpath ..\..\build\classes jnidemo.MainA HelloWorldNative.h C header file is generated. It is required to provide correct function declaration for the native implementation of the nativePrint() method.
1412/26/2012
Header file generated will contain the native method definition that to be implemented in C/C++ codeCopy the definitions of the following format
JNIEXPORT void JNICALL Java_ajnidemo_Main_nativePrint(JNIEnv *, jclass);
JNIEXPORT jint JNICALL Java_ajnidemo_Main_intMethod(JNIEnv *, jclass, jint);
JNIEXPORT and JNICALL are macros that expand to match platform-specific directives, it is also used to specify the calling and linkage convention of both JNI functions and native method implementations.
1512/26/2012
The first argument, of type JNIEnv, contains all the hooks that allow to call back into the JVM.
The second argument has a different meaning depending on the type of method. •For non-static methods (also called instance methods), the second argument is the equivalent of the “this” pointer in C++ and similar to “this” in Java: it’s a reference to the object that called the native method.•For static methods, it’s a reference to the Class object where the method is implemented.
The remaining arguments represent the Java objects passed into the native method call. Primitives are also passed in this way, but they come in by value.
1612/26/2012
The JNIEnv argumentJNI functions are those that the programmer uses to interact with the JVM from inside
a native method. Every JNI native method receives a special argument as its first parameter: the
JNIEnv argument, which is a pointer to a specialJNI data structure of type JNIEnv_.
One element of the JNI data structure is a pointer to anarray generated by the JVM; each element of this array is a pointer to a JNI function.
The JNI functions can be called from the native method by dereferencing these pointers
Every JVM provides its own implementation of the JNI functions
2012/26/2012
Through the JNIEnv argument, the programmer has access to a large set of functions. These functions can be grouped into the following categories:
Obtaining version informationPerforming class and object operationsHandling global and local references to Java
objectsAccessing instance fields and static fieldsCalling instance methods and static methodsPerforming string and array operationsGenerating and handling Java exceptions
2112/26/2012
In the jni.h header file, we can see that inside the #ifdef __cplusplus preprocessor conditional, the JNIEnv_ structure is defined as a class when compiled by a C++ compiler. This class contains a number of inline functions that let you access the JNIfunctions with an easy and familiar syntax
Example:In C(*jEnv) ReleaseStringUTFChars(jEnv,jMsg, msg);
In C++jEnv ReleaseStringUTFChars(jMsg, msg);
2212/26/2012
About Cygwin:Cygwin is:
a collection of tools which provide a Linux look and feel environment for Windows.a DLL (cygwin1.dll) which acts as a Linux API layer providing substantial Linux API
functionality.
Cygwin is not:a way to run native Linux apps on Windows. You must rebuild your application from
source if you want it to run on Windows.a way to magically make native Windows apps aware of UNIX® functionality like
signals, ptys, etc. Again, you need to build your apps from source if you want to take advantage of Cygwin functionality.
2312/26/2012
Before creating the C file just download and install CYGWIN to enable C/C++ package in netbeans IDE.
Steps for doing it1. Download and run the Cygwin installer
from http://www.cygwin.com/setup.exe.2. At the Choose Installation Type page, select Install
From Internet, and click Next.3. At the Choose Installation Directory page, define the
settings appropriate for the system, then click Next.4. At the Select Local Package Directory page, define
the directory which Cygwin installer will use as its cache directory, and click Next.
2412/26/2012
5. At the Select Connection Type page, choose the type of Internet connection you have, and click Next.
6. At the Choose Download Site(s) page, select a mirror which is closest to your location, and click Next.
7. At the Select Packages page, select at least these packages: gcc-core, gcc-g++, gdb, and make.
2512/26/2012
Create a C programOpen a C/C++ application and a C Main file in to it (JniCApp project name and MainC
file).press Ctrl 2 and select the Jnidemo project and select src.You can find the .h file in it. Drag and drop it the JniCApp project which will be
included in the nbproject folderremove the main method in it and paste the methods that is been copied from the
header fileinclude 2 header files in the c file
1. #include “HelloWorldNative.h”2. #include <jni.h>
Now give the method body for the methods pasted from header file as follows
2612/26/2012
JNIEXPORT void JNICALL Java_ajnidemo_Main_nativePrint(JNIEnv *env, jobject obj)
{printf("\nHello World Native ");
}JNIEXPORT jint JNICALL Java_ajnidemo_Main_intMethod(JNIEnv *env, jobject obj, jint num)
{return num+num;
}
Save, Right click and build the project
2712/26/2012
To enable jni.h header file do the following step1. Right-click the project node and choose Properties from the context menu.2. Select C Complier from categories click include directories from it I the next
dialog box click Add button, from the select directory dialog select the following paths and click ok
C:/Program Files/Java/jdk1.6.0_07/include C:/Program Files/Java/jdk1.6.0_07/include/win32
3. Now click the Additional option and type the following-mno-cygwin -Wl,--add-stdcall-alias -shared -m32
4. Select Linker from categories and type the following in outputdist/HelloWorldNative.dll which will create the .dll file in the ‘dist’ folder of JniCApp project
2812/26/2012
The -mno-cygwin option, enables building DLLs that have no dependencies on Cygwin own libraries and thus can be executed on machines which do not have Cygwin installed.
The -Wl,--add-stdcall-alias passes the --add-stdcall-alias option to the linker; without it, the resulting application would fail with the UnsatisfiedLinkError.
The -shared option tells the compiler to generate a DLL ( not an executable file).
-m32 tells the compiler to create a 32-bit binary. On 64-bit systems the compiled binaries are 64-bit by default,which causes a lot of problems with 32-bit JDKs.
2912/26/2012
Now include the .dll file in the java file as shown belowstatic {
System.load ("E:\\Programs\\AJNICApp\\dist\\HelloWorldNative.dll");} Execute your java file
3012/26/2012
Accessing Java Strings:-Java Strings are in Unicode formatif the user want to pass it to a non-Unicode function (printf( ), for example), user must
first convert it into ASCII characters with the JNI function GetStringUTFChars( ). This function takes a Java String and converts it to UTF-8 characters.
const char *str = (*env)->GetStringUTFChars(env,string,0)
to convert back to unicode format string(*env)->ReleaseStringUTFChars(env,string,str);
3212/26/2012
In the above program int value is passed as an argument. In Native methods we can also pass java object as an arguments follows
class MyJavaClass{public void divByTwo() {
aValue /= 2.0f;System.out.printn(aValue);
}public flaot aValue;}
3312/26/2012
public class UseObjects {public static void main(String [] args) {UseObjects app = new UseObjects();MyJavaClass anObj = new MyJavaClass();anObj.aValue = 2;app.changeObject(anObj);System.out.println("Java: " + anObj.aValue);}private native void changeObject(MyJavaClass obj);static {System.loadLibrary("UseObjImpl");}}
3412/26/2012
JNI Method is of the format as follows:-
JNIEXPORT void JNICALL Java_UseObjects_changeObject (JNIEnv * env, jobject jThis, jobject obj) { //body}
3512/26/2012
JNI and Java exceptions:-With JNI, Java exceptions can be thrown, caught, printed, and rethrown just as they
are inside a Java program. But it’s up to the programmer to call dedicated JNI functions to deal with exceptions.
Here are the JNI functions for exception handling:1. Throw( ) Throws an existing exception object. Used in native methods to rethrow
an exception.2. ThrowNew( ) Generates a new exception object and throws it.3. ExceptionOccurred( ) Determines if an exception was thrown and not yet
cleared.
3612/26/2012
4. ExceptionDescribe( ) Prints an exception and the stack trace.5. ExceptionClear( ) Clears a pending exception.6. FatalError( ) Raises a fatal error. Does not return
3712/26/2012
Example:-JAVA CODE:-class CatchThrow {private native void doit() throws IllegalArgumentException;private void callback() throws NullPointerException {throw new NullPointerException("CatchThrow.callback"); }public static void main(String args[]) {CatchThrow c = new CatchThrow();try { c.doit(); c.callback();} catch (Exception e) { System.out.println("In Java:\n\t" + e); }}static { System.loadLibrary("CatchThrow"); }}
3812/26/2012
PART OF C CODE:-JNIEXPORT void JNICALLJava_CatchThrow_doit(JNIEnv *env, jobject obj){- - -exc = (*env)->ExceptionOccurred(env);if (exc) {- - -(*env)->ExceptionDescribe(env);(*env)->ExceptionClear(env);- - -}(*env)->ThrowNew(env, newExcCls, "thrown from C code");}
4112/26/2012
When two or more threads need access to a shared resource, they need some way to ensure that the resource will be used by only one thread at a time.
The process by which this is achieved is called synchronization.
Java provides unique, language-level support for it.Key to synchronization is the concept of the monitor
(also called a semaphore). A monitor is an object that is used as a mutually
exclusive lock, or mutex.
4212/26/2012
Only one thread can own a monitor at a given time. When a thread acquires a lock, it is said to have entered the monitor. All other threads attempting to enter the locked monitor will be
suspended until the first thread exits the monitor. These other threads are said to be waiting for the monitor. A thread that owns a monitor can reenter the same monitor if it so desires.synchronization can be done in two ways using synchronized keyword
1. Applying for a method (synchronized Method)2. Applying for a Statement (synchronized Block)
4512/26/2012
Example: Without Using Synchronization
Here is the output produced by this program:Hello[Synchronized[World]]]
4912/26/2012
JNI and ThreadsThe Java virtual machine supports multiple threads of control concurrently executing
in the same address space. This concurrency introduces a degree of complexity that user do not have in a single-
threaded environment. Multiple threads may access the same objects, the same file descriptors, the same
shared resources--at the same time.Constraints
There are certain constraints that user must keep in mind when writing native methods that are to run in a multithreaded environment.
By understanding and programming within these constraints, native methods will execute safely no matter how many threads simultaneously execute a given native method.
5012/26/2012
For example:A JNIEnv pointer is only valid in the thread associated with it, user should not pass
this pointer from one thread to another, or cache and use it in multiple threads. The JVM passes a native method the same JNIEnv pointer in consecutive invocations
from the same thread, but passes different JNIEnv pointers when invoking that native method from different threads.
Local references are valid only in the thread that created them. User should not pass local references from one thread to another. User should always convert local references to global references whenever there is a possibility that multiple threads may use the same reference.
5112/26/2012
Monitor Entry and Exit
Monitors are the primitive synchronization mechanism on the Java platform. Each object can be dynamically associated with a monitor. The JNI allows user to synchronize using these monitors, thus implementing the
functionality equivalent to a synchronized block in the Java programming language:
synchronized (obj) {
... // synchronized block}
5212/26/2012
The Java virtual machine guarantees that a thread acquires the monitor associated with the object obj before it executes any statements in the block.
This ensures that there can be at most one thread that holds the monitor and executes inside the synchronized block at any given time.
A thread blocks when it waits for another thread to exit a monitor.Native code can use JNI functions to perform equivalent synchronization on JNI
references. User can use the MonitorEnter function to enter the monitor and the MonitorExit
function to exit the monitor:
5312/26/2012
if ((*env)->MonitorEnter(env, obj) != JNI_OK) {
... /* error handling */}... /* synchronized block */if ((*env)->MonitorExit(env, obj) != JNI_OK){
... /* error handling */};
5412/26/2012
Executing the code above, a thread must first enter the monitor associated with objbefore executing any code inside the synchronized block.
The Monitor-Enter operation takes a jobject as an argument and blocks if another thread has already entered the monitor associated with the jobject.
Calling MonitorExit when the current thread does not own the monitor results in an error and causes an IllegalMonitorStateException to be raised.
The above code contains a matched pair of MonitorEnter and MonitorExit calls, yet user still need to check for possible errors. Monitor operations may fail if, for example, the underlying thread implementation cannot allocate the resources necessary to perform the monitor operation.
5512/26/2012
MonitorEnter and MonitorExit work on jclass, jstring, and jarray types, which are special kinds of jobject references.
Remember to match a MonitorEnter call with the appropriate number of MonitorExit calls, especially in code that handles errors and exceptions:if ((*env)->MonitorEnter(env, obj) != JNI_OK) ...;...if ((*env)->ExceptionOccurred(env)) {... /* exception handling *//* remember to call MonitorExit here */if ((*env)->MonitorExit(env, obj) != JNI_OK) ...;}... /* Normal execution path.if ((*env)->MonitorExit(env, obj) != JNI_OK) ...;
5612/26/2012
Failure to call MonitorExit will most likely lead to deadlocks. By comparing the above C code segment with the code segment at the beginning of
this section, user can appreciate how much easier it is to program with the Java programming language than with the JNI.
Thus, it is preferable to express synchronization constructs in the Java programming language.
If, for example, a static native method needs to enter the monitor associated with its defining class, we should define a static synchronized native method as opposed to performing JNI-level monitor synchronization in native code.
5712/26/2012
Monitor Wait and NotifyThe Java API contains several other methods that are
useful for thread synchronization. They are Object.wait, Object.notify, and
Object.notifyAll. No JNI functions are supplied that correspond directly
to these methods because monitor wait and notify operations are not as performance critical as monitor enter and exit operations.
Native code may instead use the JNI method call mechanism to invoke the corresponding methods in the Java API:
5812/26/2012
/* precomputed method IDs */static jmethodID MID_Object_wait;static jmethodID MID_Object_notify;static jmethodID MID_Object_notifyAll;void JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout){(*env)->CallVoidMethod(env, object, MID_Object_wait, timeout); }
Void JNU_MonitorNotify(JNIEnv *env, jobject object){ (*env)->CallVoidMethod(env, object, MID_Object_notify); }
Void JNU_MonitorNotifyAll(JNIEnv *env, jobject object){(*env)->CallVoidMethod(env, object, MID_Object_notifyAll); }
5912/26/2012
User assume that the method IDs for Object.wait, Object.notify, and Object.notifyAll have beencalculated elsewhere and are cached in the global variables.
Like in the Java programming language, user can call the above monitor-related functions only when holding the monitor associated with the jobject argument.
6012/26/2012
Obtaining a JNIEnv Pointer in Arbitrary Contextsexplained earlier that a JNIEnv pointer is only valid in its associated thread. This is generally not a problem for native methods because they receive the JNIEnv
pointer from the virtual machine as thefirst argument.
Occasionally, however, it may be necessary for a piece of native code not called directly from the virtual machine to obtain the JNIEnv interface pointer that belongs to the current thread.
For example, the piece of native code may belong to a "callback" function called by the operating system, in which case the JNIEnv pointer will probably not be available as an argument.
6112/26/2012
User can obtain the JNIEnv pointer for the current thread by calling the AttachCurrentThread function of the invocation interface:JavaVM *jvm; /* already set */f(){JNIEnv *env;(*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);... /* use env */}
When the current thread is already attached to the virtual machine, Attach-Current-Thread returns the JNIEnv interface pointer that belongs to the current thread.
6212/26/2012
There are many ways to obtain the JavaVM pointer: by recording it when the virtual machine is created, by querying for the created virtual machines using JNI_GetCreatedJavaVMs, by calling the JNI function GetJavaVMinside a regular native method, or by defining a JNI_OnLoad handler.
Unlike the JNIEnv pointer, the JavaVM pointer remains valid across multiple threads so it can be cached in a global variable.
Java 2 SDK release 1.2 provides a new invocation interface function GetEnv so that you can check whether the current thread is attached to the virtual machine, and, if so, to return the JNIEnv pointer that belongs to the current thread.
GetEnv and AttachCurrentThread are functionally equivalent if the current thread is already attached to the virtual machine.