|
|
|
1000 Java Tips ebook
|
|
 

Free "1000 Java Tips" eBook is here! It is huge collection of big and small Java
programming articles and tips. Please take your copy here.
Take your copy of free "Java Technology Screensaver"!. |
|
Native From Java: Java code example
|
JavaFAQ Home » Java Code Examples

Native call from Java: These samples working illustrate how to call a native library from within Java.
It also includes a sample that attempts a simple performance (speed) comparison between the pure native, pure Java and JNI implementation.
You can find two versions:
- Native call from Java program to C program and
- Native call from Java program to C++ program
C version:
JNISamples.c
| Code: |
#include <jni.h>
#include "JNISamples.h"
#include <stdio.h>
static void printString(JNIEnv *env, jstring jstr);
JNIEXPORT void JNICALL Java_JNISamples_syncNativeMethod (JNIEnv *env, jobject obj, jobject syncObj)
{
printf("Inside synchronized native method\n");
(*env)->MonitorEnter(env, syncObj);
printf("After synchronizing syncObj\n");
(*env)->MonitorExit(env, syncObj);
printf("After releasing syncObj\n");
/*
The functions Object.wait, Object.notify, and Object.notifyAll provide
another useful thread synchronization mechanism. While the JNI does not
directly support these functions, a native method can always follow the
JNI method call mechanism to invoke them.
*/
}
JNIEXPORT void JNICALL Java_JNISamples_nativeCatchThrow (JNIEnv *env, jobject obj)
{
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mid = (*env)->GetMethodID(env, cls, "javaCatchThrow", "()V");
jthrowable exc;
jclass newException;
if(0 == mid)
{
printf("Error obtaining method id\n");
return;
}
(*env)->CallVoidMethod(env, obj, mid);
exc = (*env)->ExceptionOccurred(env);
if(exc)
{
/*
We don't do much with the exception, except that we print a debug message
using ExceptionDescribe, clear it, and throw a new exception.
*/
/*
It is extremely important to check, handle, and clear the pending exception
before calling subsequent JNI functions. Calling arbitrary JNI functions with
a pending exception may lead to unexpected results. You can safely call only
a small number of JNI functions when there is a pending exception. These
functions are ExceptionOccurred, ExceptionDescribe, and ExceptionClear.
*/
(*env)->ExceptionDescribe(env);
(*env)->ExceptionClear(env);
}
newException = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
if (newException == 0)
{
/* Unable to find the new exception class, give up. */
printf("Error finding the new exception class\n");
return;
}
(*env)->ThrowNew(env, newException, "IllegalArgumentException thrown from C code");
}
JNIEXPORT void JNICALL Java_JNISamples_fieldAccess (JNIEnv *env, jobject obj)
{
jfieldID fid;
jstring jstr;
const char *str;
jint iStaticIntValue;
jclass cls = (*env)->GetObjectClass(env, obj);
fid = (*env)->GetStaticFieldID(env, cls, "iStaticIntFld", "I");
if(0 == fid)
{
printf("Error getting fid for iStaticIntFld\n");
return;
}
iStaticIntValue = (*env)->GetStaticIntField(env, cls, fid);
printf("iStaticIntValue=%d\n", iStaticIntValue);
(*env)->SetStaticIntField(env, cls, fid, 200);
fid = (*env)->GetFieldID(env, cls, "sStringFld", "Ljava/lang/String;");
if(0 == fid)
{
printf("Error getting fid for sStringFld\n");
return;
}
jstr = (*env)->GetObjectField(env, obj, fid);
printString(env, jstr);
jstr = (*env)->NewStringUTF(env, "NewString");
(*env)->SetObjectField(env, obj, fid, jstr);
}
JNIEXPORT void JNICALL Java_JNISamples_nativeMethod (JNIEnv *env, jobject obj, jint iDepth)
{
jclass cls = (*env)->GetObjectClass(env, obj);
static jmethodID method = 0;
/*
Method ID is valid only for as long as the class
from which it is derived is not unloaded.
Obtaining a method ID is a relatively expensive operation.
Use NewGlobalRef to create a global ref in native code to
prevent the class from being garbage collected.
You MUST use DeleteGlobalRef to delete the global reference.
Use DeleteLocalRef to delete a local ref to release mem immediately.
*/
if(0 == method)
{
method = (*env)->GetMethodID(env, cls, "callback", "(I)V");
}
if (method == 0)
{
printf("Could not get method callback(I)V\n");
return;
}
printf("In C, depth = %d, about to enter Java\n", iDepth);
(*env)->CallVoidMethod(env, obj, method, iDepth);
printf("In C, depth = %d, back from Java\n", iDepth);
}
JNIEXPORT jint JNICALL Java_JNISamples_stringArrAccess(JNIEnv *env, jobject obj, jobjectArray asArr)
{
int iIndex;
jsize len = (*env)->GetArrayLength(env, asArr);
for(iIndex=0; iIndex < len; iIndex++)
{
jstring jstr = (*env)->GetObjectArrayElement(env, asArr, iIndex);
printString(env, jstr);
/* explicitly releasing to assist garbage collection, though not required */
(*env)->DeleteLocalRef(env, jstr);
}
return len;
}
JNIEXPORT jintArray JNICALL Java_JNISamples_intArrAccess (JNIEnv *env, jobject obj, jintArray aiArr)
{
int i, sum = 0;
jintArray aiRet;
jint *retBody;
jsize len = (*env)->GetArrayLength(env, aiArr);
jint *body = (*env)->GetIntArrayElements(env, aiArr, 0);
/* to copy a region of the array only, use Get/Set<type>ArrayRegion functions */
for (i=0; i<len; i++)
{
sum += body[i];
body[i]++;
}
aiRet = (*env)->NewIntArray(env, len);
retBody = (*env)->GetIntArrayElements(env, aiRet, 0);
for (i=0; i<len; i++)
{
retBody[i] = body[i];
}
(*env)->ReleaseIntArrayElements(env, aiArr, body, 0);
(*env)->ReleaseIntArrayElements(env, aiRet, retBody, 0);
return aiRet;
}
JNIEXPORT jstring JNICALL Java_JNISamples_stringAccess (JNIEnv *env, jobject obj, jstring prompt)
{
char buf[128];
const char * str = (*env)->GetStringUTFChars(env, prompt, 0);
printf("Inside Native: %s\n", str);
sprintf(buf, "Hello [%s][%d][%d]",
str,
(*env)->GetStringUTFLength(env, prompt),
(*env)->GetStringLength(env, prompt));
(*env)->ReleaseStringUTFChars(env, prompt, str);
return (*env)->NewStringUTF(env, buf);
}
static void printString(JNIEnv *env, jstring jstr)
{
const char * str = (*env)->GetStringUTFChars(env, jstr, 0);
printf("%s\n", str);
(*env)->ReleaseStringUTFChars(env, jstr, str);
}
|
JNISamples.h
| Code: |
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JNISamples */
#ifndef _Included_JNISamples
#define _Included_JNISamples
#ifdef __cplusplus
extern "C" {
#endif
/* Inaccessible static: iStaticIntFld */
/*
* Class: JNISamples
* Method: fieldAccess
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_JNISamples_fieldAccess
(JNIEnv *, jobject);
/*
* Class: JNISamples
* Method: intArrAccess
* Signature: ([I)[I
*/
JNIEXPORT jintArray JNICALL Java_JNISamples_intArrAccess
(JNIEnv *, jobject, jintArray);
/*
* Class: JNISamples
* Method: nativeCatchThrow
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_JNISamples_nativeCatchThrow
(JNIEnv *, jobject);
/*
* Class: JNISamples
* Method: nativeMethod
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_JNISamples_nativeMethod
(JNIEnv *, jobject, jint);
/*
* Class: JNISamples
* Method: stringAccess
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_JNISamples_stringAccess
(JNIEnv *, jobject, jstring);
/*
* Class: JNISamples
* Method: stringArrAccess
* Signature: ([Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_JNISamples_stringArrAccess
(JNIEnv *, jobject, jobjectArray);
/*
* Class: JNISamples
* Method: syncNativeMethod
* Signature: (Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL Java_JNISamples_syncNativeMethod
(JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif
|
JNISamples.java
| Code: |
public class JNISamples
{
private native String stringAccess(String sStr);
private native int [] intArrAccess(int [] aiInp);
private native int stringArrAccess(String [] asInp);
private native void nativeMethod(int iDepth);
private synchronized native void syncNativeMethod(Object oSync);
private native void fieldAccess();
private native void nativeCatchThrow() throws IllegalArgumentException;
static
{
System.loadLibrary("JNISamples");
}
static int iStaticIntFld;
String sStringFld;
public static void main(String [] args)
{
JNISamples sample = new JNISamples();
System.out.println("String access test");
sample.doString();
System.out.println("int array test");
sample.doIntArray();
System.out.println("String array test");
sample.doStrArray();
System.out.println("Callback test");
sample.callback(0);
System.out.println("Field access test");
sample.doFldAccess();
System.out.println("Native exception catch and throw test");
try
{
sample.nativeCatchThrow();
}
catch(IllegalArgumentException iae)
{
iae.printStackTrace();
}
System.out.println("Synchronized Native Methods");
sample.syncNativeMethod(new Object());
System.out.println("Success!");
}
private void javaCatchThrow() throws NullPointerException
{
throw new NullPointerException("Null pointer exception thrown in javaCatchThrow");
}
private void doFldAccess()
{
iStaticIntFld = 100;
sStringFld = "sStringFld";
fieldAccess();
System.out.println("In Java");
System.out.println("iStaticIntFld = " + iStaticIntFld);
System.out.println("sStringFld = " + sStringFld);
}
private void doString()
{
String sRet = stringAccess("String test");
System.out.println(sRet);
}
private void doStrArray()
{
String [] asInp = new String[10];
int iIndex, iLen;
for(iIndex=0; iIndex<10; iIndex++)
{
asInp[iIndex] = "String: " + Integer.toString(iIndex);
}
iLen = stringArrAccess(asInp);
System.out.println("String array size: " + iLen);
}
private void doIntArray()
{
int [] aiInp = new int[10];
int iIndex;
for(iIndex=0; iIndex<10; iIndex++)
{
aiInp[iIndex] = iIndex;
}
int [] aiOut = intArrAccess(aiInp);
System.out.print("Int array: {");
for(iIndex=0; iIndex<10; iIndex++)
{
System.out.print(aiInp[iIndex] + ", ");
}
System.out.println("}");
}
private void callback(int iDepth)
{
System.out.println("In Java callback. Depth=" + iDepth);
if(5 > iDepth)
{
nativeMethod(iDepth + 1);
}
else
{
System.out.println("Stopping recursion");
}
}
}
|
makefile
| Code: |
#SOLARIS
#---------------
#INCFLAGS=-I/usr/java1.2/include -I/usr/java1.2/include/solaris
#CC=cc
#CXX=CC
#LINK=ld
#KPIC_COMPILE=-KPIC
#KPIC_LINK=-G
#DIGITAL OSF
#---------------
INCFLAGS=-I/usr/opt/java122/include -I/usr/opt/java122/include/alpha -pthread
CC=cc
CXX=cxx
LINK=cc
KPIC_COMPILE=
KPIC_LINK=-shared
all : libJNISamples.so JNISamples.class
echo "All done"
JNISamples.class : JNISamples.java
javac JNISamples.java
JNISamples.h : JNISamples.class
javah -jni JNISamples
libJNISamples.so : JNISamples.o
${LINK} ${KPIC_LINK} -o libJNISamples.so JNISamples.o
JNISamples.o : JNISamples.c JNISamples.h
${CC} ${KPIC_COMPILE} -c JNISamples.c ${INCFLAGS}
|
C++ version:
JNISamples.cpp
| Code: |
#include <jni.h>
#include "JNISamples.h"
#include <iostream.h>
static void printString(JNIEnv *env, jstring jstr);
JNIEXPORT void JNICALL Java_JNISamples_syncNativeMethod (JNIEnv *env, jobject obj, jobject syncObj)
{
cout << "Inside synchronized native method\n";
env->MonitorEnter(syncObj);
cout << "After synchronizing syncObj\n";
env->MonitorExit(syncObj);
cout << "After releasing syncObj\n";
/*
The functions Object.wait, Object.notify, and Object.notifyAll provide
another useful thread synchronization mechanism. While the JNI does not
directly support these functions, a native method can always follow the
JNI method call mechanism to invoke them.
*/
}
JNIEXPORT void JNICALL Java_JNISamples_nativeCatchThrow (JNIEnv *env, jobject obj)
{
jclass cls = env->GetObjectClass(obj);
jmethodID mid = env->GetMethodID(cls, "javaCatchThrow", "()V");
jthrowable exc;
jclass newException;
if(0 == mid)
{
cout << "Error obtaining method id\n";
return;
}
env->CallVoidMethod(obj, mid);
exc = env->ExceptionOccurred();
if(exc)
{
/*
We don't do much with the exception, except that we print a debug message
using ExceptionDescribe, clear it, and throw a new exception.
*/
/*
It is extremely important to check, handle, and clear the pending exception
before calling subsequent JNI functions. Calling arbitrary JNI functions with
a pending exception may lead to unexpected results. You can safely call only
a small number of JNI functions when there is a pending exception. These
functions are ExceptionOccurred, ExceptionDescribe, and ExceptionClear.
*/
env->ExceptionDescribe();
env->ExceptionClear();
}
newException = env->FindClass("java/lang/IllegalArgumentException");
if (newException == 0)
{
/* Unable to find the new exception class, give up. */
cout << "Error finding the new exception class\n";
return;
}
env->ThrowNew(newException, "IllegalArgumentException thrown from C code");
}
JNIEXPORT void JNICALL Java_JNISamples_fieldAccess (JNIEnv *env, jobject obj)
{
jfieldID fid;
jstring jstr;
const char *str;
jint iStaticIntValue;
jclass cls = env->GetObjectClass(obj);
fid = env->GetStaticFieldID(cls, "iStaticIntFld", "I");
if(0 == fid)
{
cout << "Error getting fid for iStaticIntFld\n";
return;
}
iStaticIntValue = env->GetStaticIntField(cls, fid);
cout << "iStaticIntValue=" << iStaticIntValue << "\n";
env->SetStaticIntField(cls, fid, 200);
fid = env->GetFieldID(cls, "sStringFld", "Ljava/lang/String;");
if(0 == fid)
{
cout << "Error getting fid for sStringFld\n";
return;
}
jstr = (jstring)env->GetObjectField(obj, fid);
printString(env, jstr);
jstr = env->NewStringUTF("NewString");
env->SetObjectField(obj, fid, jstr);
}
JNIEXPORT void JNICALL Java_JNISamples_nativeMethod (JNIEnv *env, jobject obj, jint iDepth)
{
jclass cls = env->GetObjectClass(obj);
static jmethodID method = 0;
/*
Method ID is valid only for as long as the class
from which it is derived is not unloaded.
Obtaining a method ID is a relatively expensive operation.
Use NewGlobalRef to create a global ref in native code to
prevent the class from being garbage collected.
You MUST use DeleteGlobalRef to delete the global reference.
Use DeleteLocalRef to delete a local ref to release mem immediately.
*/
if(0 == method)
{
method = env->GetMethodID(cls, "callback", "(I)V");
}
if (method == 0)
{
cout << "Could not get method callback(I)V\n";
return;
}
cout << "In C, depth = " << iDepth << "about to enter Java\n";
env->CallVoidMethod(obj, method, iDepth);
cout << "In C, depth = " << iDepth << ", back from Java\n";
}
JNIEXPORT jint JNICALL Java_JNISamples_stringArrAccess(JNIEnv *env, jobject obj, jobjectArray asArr)
{
int iIndex;
jsize len = env->GetArrayLength(asArr);
for(iIndex=0; iIndex < len; iIndex++)
{
jstring jstr = (jstring)env->GetObjectArrayElement(asArr, iIndex);
printString(env, jstr);
/* explicitly releasing to assist garbage collection, though not required */
env->DeleteLocalRef(jstr);
}
return len;
}
JNIEXPORT jintArray JNICALL Java_JNISamples_intArrAccess (JNIEnv *env, jobject obj, jintArray aiArr)
{
int i, sum = 0;
jintArray aiRet;
jint *retBody;
jsize len = env->GetArrayLength(aiArr);
jint *body = env->GetIntArrayElements(aiArr, 0);
/* to copy a region of the array only, use Get/Set<type>ArrayRegion functions */
for (i=0; i<len; i++)
{
sum += body[i];
body[i]++;
}
aiRet = env->NewIntArray(len);
retBody = env->GetIntArrayElements(aiRet, 0);
for (i=0; i<len; i++)
{
retBody[i] = body[i];
}
env->ReleaseIntArrayElements(aiArr, body, 0);
env->ReleaseIntArrayElements(aiRet, retBody, 0);
return aiRet;
}
JNIEXPORT jstring JNICALL Java_JNISamples_stringAccess (JNIEnv *env, jobject obj, jstring prompt)
{
char buf[128];
const char * str = env->GetStringUTFChars(prompt, 0);
cout << "Inside Native: " << str << "\n";
sprintf(buf, "Hello [%s][%d][%d]",
str,
env->GetStringUTFLength(prompt),
env->GetStringLength(prompt));
env->ReleaseStringUTFChars(prompt, str);
return env->NewStringUTF(buf);
}
static void printString(JNIEnv *env, jstring jstr)
{
const char * str = env->GetStringUTFChars(jstr, 0);
cout << str << "\n";
env->ReleaseStringUTFChars(jstr, str);
}
|
JNISamples.h
| Code: |
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JNISamples */
#ifndef _Included_JNISamples
#define _Included_JNISamples
#ifdef __cplusplus
extern "C" {
#endif
/* Inaccessible static: iStaticIntFld */
/*
* Class: JNISamples
* Method: fieldAccess
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_JNISamples_fieldAccess
(JNIEnv *, jobject);
/*
* Class: JNISamples
* Method: intArrAccess
* Signature: ([I)[I
*/
JNIEXPORT jintArray JNICALL Java_JNISamples_intArrAccess
(JNIEnv *, jobject, jintArray);
/*
* Class: JNISamples
* Method: nativeCatchThrow
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_JNISamples_nativeCatchThrow
(JNIEnv *, jobject);
/*
* Class: JNISamples
* Method: nativeMethod
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_JNISamples_nativeMethod
(JNIEnv *, jobject, jint);
/*
* Class: JNISamples
* Method: stringAccess
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_JNISamples_stringAccess
(JNIEnv *, jobject, jstring);
/*
* Class: JNISamples
* Method: stringArrAccess
* Signature: ([Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_JNISamples_stringArrAccess
(JNIEnv *, jobject, jobjectArray);
/*
* Class: JNISamples
* Method: syncNativeMethod
* Signature: (Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL Java_JNISamples_syncNativeMethod
(JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif
|
JNISamples.java
| Code: |
public class JNISamples
{
private native String stringAccess(String sStr);
private native int [] intArrAccess(int [] aiInp);
private native int stringArrAccess(String [] asInp);
private native void nativeMethod(int iDepth);
private synchronized native void syncNativeMethod(Object oSync);
private native void fieldAccess();
private native void nativeCatchThrow() throws IllegalArgumentException;
static
{
System.loadLibrary("JNISamples");
}
static int iStaticIntFld;
String sStringFld;
public static void main(String [] args)
{
JNISamples sample = new JNISamples();
System.out.println("String access test");
sample.doString();
System.out.println("int array test");
sample.doIntArray();
System.out.println("String array test");
sample.doStrArray();
System.out.println("Callback test");
sample.callback(0);
System.out.println("Field access test");
sample.doFldAccess();
System.out.println("Native exception catch and throw test");
try
{
sample.nativeCatchThrow();
}
catch(IllegalArgumentException iae)
{
iae.printStackTrace();
}
System.out.println("Synchronized Native Methods");
sample.syncNativeMethod(new Object());
System.out.println("Success!");
}
private void javaCatchThrow() throws NullPointerException
{
throw new NullPointerException("Null pointer exception thrown in javaCatchThrow");
}
private void doFldAccess()
{
iStaticIntFld = 100;
sStringFld = "sStringFld";
fieldAccess();
System.out.println("In Java");
System.out.println("iStaticIntFld = " + iStaticIntFld);
System.out.println("sStringFld = " + sStringFld);
}
private void doString()
{
String sRet = stringAccess("String test");
System.out.println(sRet);
}
private void doStrArray()
{
String [] asInp = new String[10];
int iIndex, iLen;
for(iIndex=0; iIndex<10; iIndex++)
{
asInp[iIndex] = "String: " + Integer.toString(iIndex);
}
iLen = stringArrAccess(asInp);
System.out.println("String array size: " + iLen);
}
private void doIntArray()
{
int [] aiInp = new int[10];
int iIndex;
for(iIndex=0; iIndex<10; iIndex++)
{
aiInp[iIndex] = iIndex;
}
int [] aiOut = intArrAccess(aiInp);
System.out.print("Int array: {");
for(iIndex=0; iIndex<10; iIndex++)
{
System.out.print(aiInp[iIndex] + ", ");
}
System.out.println("}");
}
private void callback(int iDepth)
{
System.out.println("In Java callback. Depth=" + iDepth);
if(5 > iDepth)
{
nativeMethod(iDepth + 1);
}
else
{
System.out.println("Stopping recursion");
}
}
}
|
makefile
| Code: |
all : libJNISamples.so JNISamples.class
echo "All done"
JNISamples.class : JNISamples.java
javac JNISamples.java
JNISamples.h : JNISamples.class
javah -jni JNISamples
libJNISamples.so : JNISamples.o
cxx -shared -o libJNISamples.so JNISamples.o
JNISamples.o : JNISamples.cpp JNISamples.h
cxx -c JNISamples.cpp -I/usr/opt/java122/include -I/usr/opt/java122/include/alpha -pthread
|
Printer Friendly Page
Send to a Friend
..
Search here again if you need more info!
|
|
|