Vous êtes sur la page 1sur 62

SUBCODE:IT0407

SUBNAME:INTEGRATIVEPROGRAMMING&
TECHNOLOGIES
SEM:VII
N.J.Subashini
AssistantProfessor,(Sr.G)
SRMUniversity,Kattankulathur

12/26/2012 1
UNIT I

12/26/2012 2
UNIT 1 LANGUAGE INTEROPERABILITY IN
JAVA 9
Using non-Java code: The Java Native Interface
- Calling a native method -Implementing your DLL
- Accessing JNI functions - Passing and using
Java objects - JNI and Java exceptions-JNI and
threading

12/26/2012 3
Introduction

12/26/2012 4
to access the non java codes different vendors
provides different solutions
9 Java 1.1 has the Java Native Interface (JNI)
9Netscape has proposed its Java Runtime Interface
9Microsoft 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)
12/26/2012 5
Java Native Interface

12/26/2012 6
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.

12/26/2012 7
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 methods
Catch and throw exceptions
Load classes and obtain class information
Perform runtime type checking
Thus, virtually everything which can be done with
classes and objects in ordinary Java can also be done
in native methods.
12/26/2012 8
Steps for creating a JNI Program:-
1. Create a java file with a native methods
2. Create header file for the java file
3. Create C file using the header file
generated for the java file, which have
the native method structure
4. Create .dll file
5. Execute the program

12/26/2012 9
12/26/2012 10
Create a java file with a native methods:-
Create a new project called as JniDemo, dont remove the check boxes in it
a project with a subpackage called jnidemo and a class called Main will be opened.
now include the following code in it

12/26/2012 11
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

12/26/2012 12
Create header file for the java file
To create the .h file for the java file use the following
command
E:\Programs\Jnidemo\src\jnidemo>"C:\Program
Files\Java\jdk1.6.0_07\bin\javah.exe" -o
HelloWorldNaive.h -jni -classpath ..\..\build\classes
jnidemo.Main
A HelloWorldNative.h C header file is generated.
It is required to provide correct function declaration
for the native implementation of
the nativePrint() method.

12/26/2012 13
Header file generated will contain the native method definition that to be implemented
in C/C++ code
Copy 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.

12/26/2012 14
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: its a
reference to the object that called the native method.
For static methods, its 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.

12/26/2012 15
The JNIEnv argument
JNI 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 special
JNI data structure of type JNIEnv_.
One element of the JNI data structure is a pointer to an
array 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

12/26/2012 16
12/26/2012 17
JNI Primitive Types

12/26/2012 18
JNI Reference Types

12/26/2012 19
Through the JNIEnv argument, the programmer has
access to a large set of functions. These functions can
be grouped into the following categories:
9 Obtaining version information
9 Performing class and object operations
9 Handling global and local references to Java
objects
9 Accessing instance fields and static fields
9 Calling instance methods and static methods
9 Performing string and array operations
9 Generating and handling Java exceptions

12/26/2012 20
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 JNI
functions with an easy and familiar syntax
Example:
In C
(*jEnv)ReleaseStringUTFChars(jEnv,jMsg, msg);

In C++
jEnvReleaseStringUTFChars(jMsg, msg);

12/26/2012 21
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.

12/26/2012 22
Before creating the C file just download and install
CYGWIN to enable C/C++ package in netbeans IDE.
Steps for doing it
1. 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.
12/26/2012 23
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.

12/26/2012 24
Create a C program
Open 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 folder
remove the main method in it and paste the methods that is been copied from the
header file
include 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

12/26/2012 25
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

12/26/2012 26
To enable jni.h header file do the following step
1. 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
9 C:/Program Files/Java/jdk1.6.0_07/include
9 C:/Program Files/Java/jdk1.6.0_07/include/win32
3. Now click the Additional option and type the following
9 -mno-cygwin -Wl,--add-stdcall-alias -shared -m32
4. Select Linker from categories and type the following in output
9 dist/HelloWorldNative.dll which will create the .dll file in the dist folder of
JniCApp project

12/26/2012 27
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.

12/26/2012 28
Now include the .dll file in the java file as shown below
static {
System.load ("E:\\Programs\\AJNICApp\\dist\\HelloWorldNative.dll");
}
Execute your java file

12/26/2012 29
Accessing Java Strings:-
Java Strings are in Unicode format
if 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);

12/26/2012 30
Passing and using Java objects

12/26/2012 31
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;
}

12/26/2012 32
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");
}
}

12/26/2012 33
JNI Method is of the format as follows:-

JNIEXPORT void JNICALL Java_UseObjects_changeObject (


JNIEnv * env, jobject jThis, jobject obj)
{
//body
}

12/26/2012 34
JNI and Java exceptions:-
With JNI, Java exceptions can be thrown, caught, printed, and rethrown just as they
are inside a Java program.
But its 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.

12/26/2012 35
4. ExceptionDescribe( ) Prints an exception and the stack trace.
5. ExceptionClear( ) Clears a pending exception.
6. FatalError( ) Raises a fatal error. Does not return

12/26/2012 36
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"); }
}

12/26/2012 37
PART OF C CODE:-
JNIEXPORT void JNICALL
Java_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");
}

12/26/2012 38
JNI and threading

12/26/2012 39
Synchronization

12/26/2012 40
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.

12/26/2012 41
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)

12/26/2012 42
12/26/2012 43
Using Synchronized Methods

12/26/2012 44
Example: Without Using Synchronization

Hereistheoutputproducedbythisprogram:
Hello[Synchronized[World]
]
]

12/26/2012 45
Example: With Synchronization

OUTPUT:
[Hello]
[World]
[Synchronized]

12/26/2012 46
The synchronized Statement

12/26/2012 47
Example: With Synchronization statement

Output:
[Hello]
[World]
[Synchronized]

12/26/2012 48
JNI and Threads
The 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.

12/26/2012 49
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.

12/26/2012 50
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
}

12/26/2012 51
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:

12/26/2012 52
if ((*env)->MonitorEnter(env, obj) != JNI_OK)
{
... /* error handling */
}
... /* synchronized block */
if ((*env)->MonitorExit(env, obj) != JNI_OK){
... /* error handling */
};

12/26/2012 53
Executing the code above, a thread must first enter the monitor associated with obj
before 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.

12/26/2012 54
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) ...;

12/26/2012 55
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.

12/26/2012 56
Monitor Wait and Notify
The 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:
12/26/2012 57
/* 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); }

12/26/2012 58
User assume that the method IDs for Object.wait,
Object.notify, and Object.notifyAll have been
calculated 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.

12/26/2012 59
Obtaining a JNIEnv Pointer in Arbitrary Contexts
explained 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 the
first 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.

12/26/2012 60
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.

12/26/2012 61
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.

12/26/2012 62

Vous aimerez peut-être aussi