In Ubuntu 12.04, I have jdk7 from sun/oracle installed. When locate jni.h, it prints multiple locations
/usr/lib/jvm/java-6-openjdk-amd64/include/jni.h
/usr/lib/jvm/jdk1.7.0_07/include/jni.h
...
In the header file generated by JDK, there is include <jni.h>, and currently it complains
fatal error: jni.h: No such file or directory.
In my Makefile, there is no specification of locations where jni.h is. And I am asking if possible to configure certain system parameter to make path of jni.h (say, /usr/lib/jvm/jdk1.7.0_07/include/jni.h) to be known when being compiled.
asked Jan 25, 2013 at 20:19
4
You have to tell your compiler where is the include directory. Something like this:
gcc -I/usr/lib/jvm/jdk1.7.0_07/include
But it depends on your makefile.
answered Jan 25, 2013 at 20:25
jdbjdb
4,35021 silver badges21 bronze badges
2
It needs both jni.h and jni_md.h files, Try this
gcc -I/usr/lib/jvm/jdk1.7.0_07/include
-I/usr/lib/jvm/jdk1.7.0_07/include/linux filename.c
This will include both the broad JNI files and the ones necessary for linux
pevik
4,2933 gold badges31 silver badges42 bronze badges
answered Apr 10, 2015 at 12:59
1
Installing the OpenJDK Development Kit (JDK) should fix your problem.
sudo apt-get install openjdk-X-jdk
This should make you able to compile without problems.
answered Feb 13, 2015 at 8:33
hgaronfolohgaronfolo
3311 gold badge3 silver badges9 bronze badges
2
I usually define my JAVA_HOME variable like so:
export JAVA_HOME=/usr/lib/jvm/java/
Therein are the necessary include files. I sometimes add the below to my .barshrc when I compile a lot of things that need it.
answered Jul 3, 2015 at 18:37
Leo UfimtsevLeo Ufimtsev
6,0224 gold badges39 silver badges48 bronze badges
Use the following code:
make -I/usr/lib/jvm/jdk*/include
where jdk* is the directory name of your jdk installation (e.g. jdk1.7.0).
And there wouldn’t be a system-wide solution since the directory name would be different with different builds of JDK downloaded and installed. If you desire an automated solution, please include all commands in a single script and run the said script in Terminal.
answered Oct 27, 2013 at 12:53
4
Setting JAVA_INCLUDE_DIR to where jni.h is located should solve your problem (setting CPPFLAGS did not work for me)
Assuming it is /usr/lib64/java/include;
export JAVA_INCLUDE_DIR=/usr/lib64/java/include
answered Aug 24, 2017 at 21:27
karaniskaranis
511 silver badge3 bronze badges
1
For me it was a simple matter of being sure to include the JDK installation (I’d only had the JRE). My R CMD javareconf output was looking like:
Java interpreter : /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
Java version : 1.8.0_191
Java home path : /usr/lib/jvm/java-8-openjdk-amd64/jre
Java compiler : not present
Java headers gen.:
Java archive tool:
trying to compile and link a JNI program
detected JNI cpp flags :
detected JNI linker flags : -L$(JAVA_HOME)/lib/amd64/server -ljvm
gcc -std=gnu99 -I/usr/share/R/include -DNDEBUG -fpic -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c conftest.c -o conftest.o
conftest.c:1:17: fatal error: jni.h: No such file or directory
compilation terminated.
/usr/lib/R/etc/Makeconf:159: recipe for target 'conftest.o' failed
make: *** [conftest.o] Error 1
Unable to compile a JNI program
JAVA_HOME : /usr/lib/jvm/java-8-openjdk-amd64/jre
Java library path:
JNI cpp flags :
JNI linker flags :
Updating Java configuration in /usr/lib/R
Done.
And indeed there was no include file in my $JAVA_HOME. Very simple remedy:
sudo apt-get install openjdk-8-jre openjdk-8-jdk
(note that this is specifically intended to install the openJDK and not the one from Oracle)
Afterwards all is well:
Java interpreter : /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
Java version : 1.8.0_191
Java home path : /usr/lib/jvm/java-8-openjdk-amd64/jre
Java compiler : /usr/lib/jvm/java-8-openjdk-amd64/jre/../bin/javac
Java headers gen.: /usr/lib/jvm/java-8-openjdk-amd64/jre/../bin/javah
Java archive tool: /usr/lib/jvm/java-8-openjdk-amd64/jre/../bin/jar
trying to compile and link a JNI program
detected JNI cpp flags : -I$(JAVA_HOME)/../include -I$(JAVA_HOME)/../include/linux
detected JNI linker flags : -L$(JAVA_HOME)/lib/amd64/server -ljvm
gcc -std=gnu99 -I/usr/share/R/include -DNDEBUG -I/usr/lib/jvm/java-8-openjdk-amd64/jre/../include -I/usr/lib/jvm/java-8-openjdk-amd64/jre/../include/linux -fpic -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c conftest.c -o conftest.o
g++ -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o conftest.so conftest.o -L/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server -ljvm -L/usr/lib/R/lib -lR
JAVA_HOME : /usr/lib/jvm/java-8-openjdk-amd64/jre
Java library path: $(JAVA_HOME)/lib/amd64/server
JNI cpp flags : -I$(JAVA_HOME)/../include -I$(JAVA_HOME)/../include/linux
JNI linker flags : -L$(JAVA_HOME)/lib/amd64/server -ljvm
Updating Java configuration in /usr/lib/R
Done.
answered Mar 25, 2019 at 8:03
MichaelChiricoMichaelChirico
33.4k13 gold badges111 silver badges194 bronze badges
0
Above answers give you a hardcoded path solution. This is bad on so many levels (java version change, OS change, etc).
Cleaner solution is to add:
JAVA_HOME = $(shell dirname $$(readlink -f $$(which java))|sed 's^jre/bin^^')
near the top of your makefile, then add:
-I$(JAVA_HOME)/include
To your include flags.
I am posting this because I ran into the same problem and spent too much time googling for wrong answers (I am building an app on multiple platforms so the build environment needs to be transportable).
answered Mar 15, 2019 at 22:25
7
None of the posted solutions worked for me.
I had to vi into my Makefile and edit the path so that the path to the include folder and the OS subsystem (in my case, -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux) was correct. This allowed me to run make and make install without issues.
answered Feb 27, 2018 at 7:34
vphilipnycvphilipnyc
8,1768 gold badges53 silver badges79 bronze badges
In case you are on Ubuntu:
#X means 6,7,8...
apt install openjdk-X-jdk
answered May 28, 2020 at 8:28
gemfieldgemfield
3,1286 gold badges27 silver badges27 bronze badges
I don’t know if this applies in this case, but sometimes the file got deleted for unknown reasons, copying it again into the respective folder should resolve the problem.
answered Nov 13, 2018 at 23:08
Thank you for your response Lee
Do you have the actual docker image? I have tried the commands above, but it doesn’t resolve the issue. I’m running openjdk 8, python 2.7. All the modules are installed, and I don’t get any more error messages, except the ilastik_main module. Does the debug below give you any hints?
python2 CellProfiler.py --log-level=DEBUG
$HOME=/home/anja
matplotlib data path /home/anja/.local/lib/python2.7/site-packages/matplotlib/mpl-data
loaded rc file /home/anja/.local/lib/python2.7/site-packages/matplotlib/mpl-data/matplotlibrc
matplotlib version 2.2.3
interactive is False
platform is linux2
loaded modules: ['numpy.core.info', 'cellprofiler.sys', 'ctypes.os', 'gc', 'cellprofiler.time', 'logging.weakref', 'pprint', 'cellprofiler.preferences', 'unittest.sys', 'numpy.core.umath', 'h5py.version', 'zmq', 'string', 'SocketServer', 'h5py.numpy', 'numpy.lib.arraysetops', 'h5py._hl.sys', 'numpy.core._multiarray_tests', 'json.encoder', 'subprocess', 'numpy.core.machar', 'zmq.backend.cython.utils', 'h5py._conv', 'unittest.StringIO', 'numpy.ma.extras', 'numpy.fft.fftpack_lite', 'matplotlib.cbook', 'multiprocessing', 'dis', 'numpy.lib', 'logging.threading', 'cellprofiler.utilities.utf16encode', '_json', 'logging.io', 'cellprofiler.utilities.sys', 'matplotlib.cbook.warnings', 'numpy.testing._private.pytesttester', 'pyparsing', 'matplotlib.cbook.textwrap', 'abc', '_thread', 'zmq.utils.sys', 'zmq.backend.cython.error', 'numpy._globals', 'numpy.lib.npyio', 'matplotlib.sys', 'h5py.h5fd', 'numpy.fft.helper', 'cellprofiler.logging', 'ctypes.tempfile', 'optparse', 'unittest.suite', '_ctypes', 'exceptions', 'json.scanner', 'codecs', 'numpy.os', 'multiprocessing.multiprocessing', 'StringIO', 'weakref', 'numpy.core._internal', 'distutils.sys', 'numpy.lib.arraypad', 'base64', '_sre', 'h5py.sys', 'logging.sys', 'logging.re', 'select', 'ctypes._ctypes', '_heapq', 'zmq.sugar.constants', 'numpy.lib.financial', 'zmq.backend.cython.time', 'binascii', 'zmq.backend.cython._poll', 'h5py.functools', 'unittest.fnmatch', 'zmq.sugar.stopwatch', 'numpy.polynomial.chebyshev', 'logging.thread', 'cPickle', 'h5py._errors', 'numpy.polynomial.hermite_e', 'h5py._hl.datatype', 'zmq.sugar.threading', 'zmq.backend.cython.cPickle', 'h5py.h5py', 'numpy.core.fromnumeric', 'numpy.ctypeslib', 'matplotlib._version', '_ast', 'zmq.sugar.tracker', '_bisect', 'zmq.backend.cython.codecs', 'encodings.aliases', 'fnmatch', 'sre_parse', 'pickle', 'numpy.random.warnings', 'logging.cStringIO', 'numpy.lib.polynomial', 'numpy.compat', 'cellprofiler.optparse', 'numbers', 'numpy.core.records', 'strop', 'numpy.core.numeric', 'six', 'matplotlib.testing', 'cellprofiler.tempfile', 'ctypes.util', 'numpy.lib.utils', 'encodings.utf_8', 'cellprofiler.multiprocessing', 'multiprocessing.sys', 'numpy.lib.arrayterator', 'zmq.sugar.atexit', 'os.path', '_weakrefset', 'zmq.backend.select', 'unittest.traceback', 'unittest.os', 'h5py._hl.selections2', 'functools', 'sysconfig', 'zmq.sugar', 'numpy.core.numerictypes', 'numpy.polynomial.legendre', 'uuid', 'numpy.matrixlib.defmatrix', 'tempfile', 'numpy.polynomial.laguerre', 'multiprocessing.os', 'multiprocessing.itertools', 'numpy.core', 'numpy.linalg.info', 'unittest.functools', 'unittest.util', 'logging.logging', 'httplib', 'h5py.operator', 'decimal', 'numpy.lib._datasource', 'logging.handlers', 'token', 'h5py', 'numpy.linalg._umath_linalg', 'cStringIO', 'numpy.polynomial', 'numpy.add_newdocs', 'zmq.sugar.frame', 'multiprocessing.process', 'ctypes.errno', 'encodings', 'cellprofiler.zmq', 'zmq.utils.strtypes', 'zmq.backend.cython.struct', 'zmq.sugar.poll', 'distutils.string', 'rfc822', 'numpy.lib.numpy', 'numpy.random.threading', 're', 'math', 'ast', 'zmq.utils.constant_names', 'numpy.lib.ufunclike', 'ctypes.struct', '_sysconfigdata_nd', 'numpy.testing._private', 'matplotlib.json', 'zmq.backend.cython.warnings', '_locale', 'logging', 'thread', 'traceback', 'cellprofiler.h5py', 'zmq.backend.platform', 'multiprocessing.threading', 'multiprocessing.util', 'ctypes.re', 'cellprofiler.threading', '_collections', 'numpy.random', 'zmq.sugar.sys', 'numpy.lib.twodim_base', 'array', 'ctypes.sys', 'posixpath', 'numpy.core.arrayprint', 'types', 'zmq.backend.cython._device', 'numpy.lib.stride_tricks', 'numpy.lib.scimath', 'matplotlib.cbook.functools', 'json._json', '_codecs', 'numpy.__config__', 'encodings.ascii', 'h5py._proxy', 'zmq.sugar.socket', 'copy', 'hashlib', 'zmq.error', 'keyword', 'numpy.lib.nanfunctions', '_warnings', 'posix', 'h5py.h5ac', 'logging.socket', 'sre_compile', '_hashlib', 'zmq.utils.itertools', 'numpy.lib.shape_base', 'numpy._import_tools', 'logging.collections', '__main__', 'numpy.fft.info', 'numpy.sys', 'dateutil._version', 'matplotlib._color_data', 'unittest.result', 'bz2', 'h5py._hl.dataset', 'encodings.codecs', 'unittest.difflib', '_ssl', 'numpy.lib.index_tricks', 'warnings', 'zmq.sugar.cPickle', 'zmq.backend.cython.sys', 'cellprofiler.weakref', 'zmq.backend.cython.random', 'h5py.utils', 'h5py._hl.filters', '_io', 'linecache', 'h5py.collections', 'numpy.linalg.linalg', 'numpy.lib._iotools', 'imp', 'random', 'unittest.types', 'zmq.sugar.context', 'datetime', 'urllib', 'logging.os', 'ctypes._endian', 'encodings.encodings', 'unittest.pprint', 'numpy.random.mtrand', 'logging.stat', '_cython_0_28_3', '_cython_0_28_5', 'h5py.h5ds', 'six.moves.urllib.request', 'numpy.linalg', 'h5py._hl', 'numpy.lib._version', 'zmq.backend.cython.threading', 'ssl', 'numpy.version', 'distutils.re', 'h5py.h5g', 'numpy.lib.type_check', 'bisect', 'h5py.h5a', 'cellprofiler.uuid', 'unittest.re', 'threading', 'zmq.ctypes', 'h5py._hl.six', 'cycler', 'tokenize', 'locale', 'atexit', 'zmq.backend.cython.message', 'unittest.weakref', 'h5py.defs', 'dateutil', 'h5py.h5z', 'h5py.h5t', 'h5py.h5p', 'h5py.h5s', 'h5py.h5r', 'h5py.h5l', 'h5py.h5o', 'h5py.h5i', 'h5py.h5d', 'zmq.sys', 'h5py.h5f', 'ctypes.subprocess', 'fcntl', 'unittest.case', 'h5py.weakref', 'zmq.utils', 'numpy.lib.info', 'ctypes', 'matplotlib', 'json.re', 'unittest.signal', 'itertools', 'numpy.fft.fftpack', 'opcode', 'six.moves', 'numpy.testing._private.nosetester', 'zmq.errno', 'unittest', 'logging.errno', 'numpy.testing._private.utils', 'h5py._hl.selections', 'unittest.collections', 'pkgutil', 'platform', 'zmq.backend.cython', 'logging.struct', 'sre_constants', 'zmq.backend.os', 'numpy.core._methods', 'numpy.core.function_base', 'numpy.compat.py3k', 'numpy', 'subprocess32', 'numpy.ma', 'logging.atexit', 'logging.cPickle', 'matplotlib.cbook._backports', 'cellprofiler.numpy', 'cellprofiler.os', 'h5py._objects', 'zlib', 'multiprocessing.weakref', 'json.decoder', 'copy_reg', 'site', 'h5py._hl.compat', 'h5py._hl.os', 'io', 'multiprocessing.atexit', 'h5py._hl.attrs', 'shutil', 'h5py.gc', 'zmq.sugar.zmq', 'zmq.backend.sys', 'h5py.platform', 'cellprofiler.utilities', 'unittest.time', 'zmq.zmq', 'matplotlib.rcsetup', 'zmq.os', 'cellprofiler.traceback', 'numpy.polynomial.polyutils', 'json.json', 'sys', 'numpy.compat._inspect', 'multiprocessing.subprocess', 'matplotlib.fontconfig_pattern', '_weakref', 'difflib', 'h5py._hl.codecs', 'urlparse', 'unittest.warnings', 'gzip', 'cellprofiler.cellprofiler', 'heapq', 'distutils', 'h5py.warnings', 'numpy.core.einsumfunc', 'zmq.backend.cython.socket', 'zmq.sugar.attrsettr', 'matplotlib.cbook.deprecation', 'matplotlib.colors', 'zmq.backend.cython.constants', 'struct', 'numpy.random.info', 'numpy.testing', 'logging.config', 'collections', 'h5py._hl.files', 'unittest.main', 'distutils.types', 'zipimport', 'zmq.sugar.errno', 'h5py._hl.group', 'textwrap', 'zmq.platform', 'cellprofiler.utilities.itertools', 'h5py._hl.base', 'zmq.backend.cython._version', 'signal', 'numpy.random.operator', 'numpy.core.multiarray', 'zmq.backend.cython.context', 'distutils.version', 'numpy.ma.core', 'numpy.core.getlimits', 'matplotlib.compat.subprocess', 'zmq.backend.cython.copy', 'logging.traceback', 'numpy.matrixlib', '_multiprocessing', 'backports', 'numpy.lib.mixins', '_posixsubprocess32', 'glob', 'mpl_toolkits', 'UserDict', 'inspect', 'six.moves.urllib', 'zmq.sugar.random', 'h5py.h5py_warnings', 'unittest.runner', 'unittest.loader', '_functools', 'json.sys', 'socket', 'cellprofiler.cStringIO', 'numpy.core.memmap', 'zmq.sugar.version', 'cython_runtime', 'numpy.linalg.lapack_lite', 'os', 'marshal', 'h5py.h5', '__future__', 'numpy.core.shape_base', 'cellprofiler', 'matplotlib.compat', '__builtin__', 'operator', 'json.struct', 'errno', '_socket', 'json', 'numpy.lib.histograms', 'multiprocessing._multiprocessing', 'encodings.__builtin__', 'zmq.backend.cython.zmq', 'cellprofiler.random', 'numpy._distributor_init', 'pwd', 'future_builtins', 'zmq.backend', '_sysconfigdata', '_struct', 'numpy.fft', 'numpy.random.numpy', 'logging.time', 'logging.SocketServer', 'numpy.lib.function_base', 'logging.warnings', 'mimetools', 'multiprocessing.signal', 'logging.codecs', '_random', 'numpy.polynomial._polybase', 'zmq.utils.zmq', 'numpy.polynomial.hermite', 'contextlib', 'cellprofiler.__main__', 'numpy.polynomial.polynomial', 'logging.types', 'grp', 'zmq.sugar.warnings', 'numpy.core.defchararray', 'gettext', '_abcoll', 'cellprofiler.re', 'zmq.sugar.time', 'genericpath', 'stat', 'ruamel', 'zmq.utils.jsonapi', 'urllib2', 'unittest.signals', 'backports.functools_lru_cache', 'ctypes.ctypes', 'numpy.lib.format', 'sitecustomize', 'numpy.testing._private.decorators', 'time']
Using /home/anja/software/CellProfiler/plugins as imagej plugin directory
Adding /home/anja/software/CellProfiler/plugins to class path
Skipping /home/anja/software/CellProfiler/plugins/loadimagesfromomero.py
JVM will be started with AWT in headless mode
Creating JVM object
Signalling caller
Enabled Bio-formats directory cacheing
Traversing file system
Exception fetching new version information from http://cellprofiler.org/CPupdate.html: HTTP Error 404: Not Found
CACHEDIR=/home/anja/.cache/matplotlib
Using fontManager instance from /home/anja/.cache/matplotlib/fontList.json
backend WXAgg version unknown
ilastik import: failed to import the ilastik. Please follow the instructions on "http://www.ilastik.org" to install ilastik Traceback (most recent call last): File "/home/anja/software/CellProfiler/cellprofiler/modules/classifypixels.py", line 71, in <module> from ilastik.core.dataMgr import DataMgr, DataItemImage ImportError: No module named ilastik.core.dataMgr ilastik import: failed to import the ilastik. Please follow the instructions on "http://www.ilastik.org" to install ilastik Traceback (most recent call last): File "/home/anja/software/CellProfiler/cellprofiler/modules/ilastik_pixel_classification.py", line 70, in <module> import ilastik_main ImportError: No module named ilastik_main HDF5Dict.__init__(): /tmp/CpmeasurementsidoTUu.hdf5, temporary=False, copy=None, mode=w Failed to stop Ilastik
When writing applications in Java, there are times when Java alone fails to meet the needs of an application. You might want to use a feature not present in the standard Java class library or you might just want to use an existing library written in some other language. That’s where JNI comes in.
I found that most of the online documentation on JNI seems pretty scattered and obsolete. Therefore the scope of this post is to show you how to implement JNI with simple examples for :
- Writing a HelloWorld in C and calling it from Java
- Passing Integers and Strings from C to Java
- Passing object Arrays from C to Java
The same can be implemented with C++ too. Note the modification mentioned in step 4 below.
Clone all the examples from Git
HelloWorld from C
1. Write the Java code
//HelloWorld.java
public class HelloWorld
{
native void cfunction();//Declaring the native function
static
{
System.loadLibrary("forhelloworld");//Linking the native library
} //which we will be creating.
public static void main(String args[])
{
HelloWorld obj = new HelloWorld();
obj.cfunction();//Calling the native function
}
}
2. Compile the Java code and generate the class file
javac HelloWorld.java
3. Generate a Header file from the class file
javah HelloWorld
This will generate a file HelloWorld.h which contains :
//HelloWorld.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: cfunction
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_cfunction
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
3. Obtain the JNI function signature from the header file
- These 2 lines make up the function header :
JNIEXPORT void JNICALL Java_HelloWorld_cfunction (JNIEnv *, jobject);
Even if we declare native functions with no arguments, the JNI function signature still holds 2 arguments, they are:
- JNIEnv * : A pointer referencing all the JNI functions
- jobject : An equivalent of this pointer
4. Write the native code using the function signature
- Add the header file jni.h
- Instead of the main() function, use the function signature obtained from the previous step.
- Add argument variables for JNIEnv (env) and Jobject (jobj).
- IMPORTANT :: If the native code is in C++, please note the only modification to be made is that the JNI functions should be called as env->func_name() instead of (*env)->func_name(). That is because C uses structures while C++ uses classes.
//HelloWorld.c
#include <jni.h>
#include <stdio.h>
JNIEXPORT void JNICALL Java_HelloWorld_cfunction
(JNIEnv *env, jobject jobj)
{
printf("n > C says HelloWorld !n");
}
5. Generate the library file from the native code
gcc -o libforhelloworld.so -shared -fPIC -I (PATH TO jni.h header) HelloWorld.c -lc
- libforhelloworld.so is the name of the native library you are going to create, it should be named as “lib”+(the library name used in the load library statement within the java code)
- -fPIC is some sort optimization for loading the machine code into the RAM, gcc requested this flag to be set. Might not be required for all systems.
If you don’t specify the path correctly you will encounter this error :
HelloWorld.c:1:17: fatal error: jni.h: No such file or directory
#include <jni.h>
^
compilation terminated.
It is usually present inside
/usr/lib/jvm/default-java/include
or
/usr/lib/jvm/java-1.7.0-openjdk-amd64/include
depending upon the version of Java you have installed in your system.
6. Place the library file in the standard /usr/lib folder
If the previous command executed successfully, it would have generated a file libforhelloworld.so . Conventionally this library file need not be placed anywhere else, it needs to reside in the current working directory.
But for that to work you need to have set the JAVA_PATH variables correctly, in most cases they won’t be set correctly. An easy hack to this would be to just place it inside /usr/lib
sudo cp libforhelloworld.so /usr/lib
If you don’t place the library file, you would encounter this error :
Exception in thread "main" java.lang.UnsatisfiedLinkError: no forhelloworld in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1886)
at java.lang.Runtime.loadLibrary0(Runtime.java:849)
at java.lang.System.loadLibrary(System.java:1088)
at HelloWorld.<clinit>(HelloWorld.java:9)
7. Execute the Java application
java HelloWorld
If you’ve followed all the steps correctly, C would greet the world 😀
> C says HelloWorld !
PASS INTEGERS FROM C TO JAVA
Example : Write a Java program to find the factorial of a number. Pass the number as an argument from Java to a native function in C which returns the factorial as an integer.
Java code
//factorial.java
import java.util.Scanner;
public class factorial
{
native int fact(int num);
static
{
System.loadLibrary("forfact");
}
public static void main(String args[])
{
Scanner inp = new Scanner(System.in);
System.out.println(" > Enter number :: ");
int num = inp.nextInt();
factorial obj = new factorial();
System.out.println(" > The factorial of "+num+" is "+obj.fact(num));
}
}
C code
//factorial.c
#include <jni.h>
#include <stdio.h>
JNIEXPORT jint JNICALL Java_factorial_fact
(JNIEnv *env, jobject jobj, jint num)
{
jint result=1;
while(num)
{
result*=num;
num--;
}
return result;
}
PASS STRINGS FROM C TO JAVA
Example : Write a Java program to reverse a given string. Pass the given string as an argument from Java to a native function in C which returns the reversed string.
Java code
//reverse.java
import java.util.Scanner;
public class reverse
{
native String reversefunc(String word);
static
{
System.loadLibrary("forreverse");
}
public static void main(String args[])
{
Scanner inp = new Scanner(System.in);
System.out.println(" > Enter a string :: ");
String word = inp.nextLine();
reverse obj = new reverse();
System.out.println(" > The reversed string is :: "+obj.reversefunc(word));
}
}
C code
//reverse.c
#include <jni.h>
#include <stdio.h>
JNIEXPORT jstring JNICALL Java_reverse_reversefunc
(JNIEnv *env,jobject jobj,jstring original)
{
const char *org;
char *rev;
org = (*env)->GetStringUTFChars(env,original,NULL);
int i;
int size = (*env)->GetStringUTFLength(env,original);
for(i=0;i<size;i++)
rev[i]=org[size-i-1];
rev[size]='';
return (*env)->NewStringUTF(env,rev);
}
PASS INTEGER ARRAYS FROM C TO JAVA
Example : Write a program that generates the first n Fibonacci numbers. Pass ‘n’ as an argument from Java to a native function in C that returns the Fibonacci numbers as an integer array.
Java code
//fibonacci.java
import java.util.Scanner;
public class fibonacci
{
native int[] returnfibo(int n);
static
{
System.loadLibrary("fibonacci");
}
public static void main(String args[])
{
Scanner inp = new Scanner(System.in);
System.out.println(" > Enter n :: ");
int n = inp.nextInt();
fibonacci obj = new fibonacci();
int[] Fibo = obj.returnfibo(n);
System.out.println(" > The first "+n+" fibonacci numbers are :: ");
for(int i=0;i<n;i++)
System.out.print(Fibo[i]+",");
}
}
C code
//fibonacci.c
#include <jni.h>
#include <stdio.h>
JNIEXPORT jintArray JNICALL Java_fibonacci_returnfibo
(JNIEnv *env,jobject jobj,jint n)
{
jintArray fiboarray = (*env)->NewIntArray(env,n);
int first=0;
int second=1;
int next;
int i;
int fibo[n];
for(i=0;i<n;i++)
{
if(i<=1)
next = i;
else
{
next = first + second;
first = second;
second = next;
}
fibo[i] = next;
}
(*env)->SetIntArrayRegion(env,fiboarray,0,n,fibo);
return fiboarray;
}
PASS STRING ARRAYS FROM C TO JAVA
Example : Write a Java program that displays the days of the week, which are passed from a native function in C.
Java code
//daysofweek.java
public class daysofweek
{
native String[] returndays();
static
{
System.loadLibrary("daysofweek");
}
static public void main(String args[])
{
daysofweek obj = new daysofweek();
String[] days = obj.returndays();
System.out.println(" > The days of the week are :: ");
for(String name: days)
System.out.println(name);
}
}
C code
//daysofweek.c
#include <jni.h>
#include <stdio.h>
JNIEXPORT jobjectArray JNICALL Java_daysofweek_returndays(JNIEnv *env, jobject jobj)
{
char *days[]={"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"};
jstring str;
jobjectArray day = 0;
jsize len = 7;
int i;
day = (*env)->NewObjectArray(env,len,(*env)->FindClass(env,"java/lang/String"),0);
for(i=0;i<7;i++)
{
str = (*env)->NewStringUTF(env,days[i]);
(*env)->SetObjectArrayElement(env,day,i,str);
}
return day;
}
As you can see, the C code is returning an array of char pointers (C strings), while the Java code is expecting an array of Java Strings. But you don’t have to worry about that, the good old implicit conversion comes to the rescue 🙂
