Calling Native Code in Java (JNI)
You can call native c/c++ code from java using the java native interface (JNI). This will provide a brief introduction and example to get started; and is for my education.
For example we can implement a method to find all the prime number from 0-100 in C and use it w/ our java app.
Our java class should look like this:
public class Primes1
{
public native int[] findPrimes();
public static void main(String[] args)
{
System.loadLibrary("Primes1");
Primes1 sample = new Primes1();
int [] primes = sample.findPrimes();
System.out.println("findPrimes: " + primes);
}
}
Now compile this code javac Primes1.java
and then run javah Primes1
. This generates a header file w/ the findPrimes method signature in - java will use this file to call your native code.
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Primes1 */
#ifndef _Included_Primes1
#define _Included_Primes1
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Primes1
* Method: findPrimes
* Signature: ()[I
*/
JNIEXPORT jintArray JNICALL Java_Primes1_findPrimes
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
Now simple implement your native code per the header file.
#include "Primes1.h"
#include <stdio.h>
#include <jni.h>
JNIEXPORT jintArray JNICALL Java_Primes1_findPrimes
(JNIEnv *env, jobject obj, jint num)
{
int i;
int index=0;
int a[num];
for(i=0; i<num; i++)
{
if(isprime(i))
{
a[index]=i;
index++;
}
}
jintArray arr = (*env)->NewIntArray(env, index);
(*env)->SetIntArrayRegion(env, arr, 0, index, a);
return arr;
}
int isprime(int n)
{
int divisor;
if (n <= 1)
{
return 0;
}
for (divisor = 2; divisor <= n-1; divisor++)
{
if (n % divisor == 0)
{
return 0;
}
}
return 1; // no matches so it's prime
}
void main(){}
Now create lib file:
$ gcc -c -I /System/Library/Frameworks/JavaVM.framework/Headers Primes1.c
$ gcc -dynamiclib -o libPrimes1.jnilib Primes1.o -framework JavaVM
Run java app
java Primes1
Speed Comparison
The below benchmarks are the execution times to find all prime numbers between 0 and 300000 using the rudimentary algorithm defined above.
The results are interesting as they are essentially all the same with the JNI example being a second slower than the pure C and pure Java implementations. I am sure this example is contrived and no true demonstration of the usefulness of JNI or the speed advantages of C over Java.
Java JNI
$ time ( java Primes1 )
real 0m25.242s
user 0m24.516s
sys 0m0.139s
Pure Java
$ time ( java PrimeJava )
real 0m24.516s
user 0m24.061s
sys 0m0.197s
Pure C
$ time ./primes
real 0m24.691s
user 0m24.279s
sys 0m0.047s
Comments are welcome below.
Permalink: calling-native-code-in-java-jni
Tags: android, java, c, jni