JNI runtime linking

The Java™ Native Interface (JNI) enables runtime linking to dynamic and static native libraries.

Information specific to z/OS® systems

If runtime linking causes a symbol conflict, the application must resolve the conflict by renaming the symbol on the application side, or by turning off runtime linking.

Dynamic linking in z/OS

When you build a C or C++ program that uses the JNI Invocation API to create a Java virtual machine, and calls Java code, use the -L option to do the following tasks:

  • Add /usr/lib and /lib to the list of directories that are searched for shared objects. All programs need shared objects that are stored in these directories.
  • Add your Java java_install_dir/lib and java_install_dir/lib/j9vm directories to the list of directories that are searched for shared objects. These directories contain the Java shared libraries. You also want to link with libjvm.so (by using the -ljvm option).

For example, this code builds an invocation API launcher namedinvAPITest by compiling the C program invAPITest.c:

cc [-q32|-q64] -Ijava_install_dir/include 
	-o invAPITest 
	-L/usr/lib 
	-L/lib 
	-Ljava_install_dir/lib/j9vm 
	-Ljava_install_dir/lib 
	-ljvm invAPITest.c

The value -q32 or -q64 specify the data model in which the program is built. If you omit these values, the default data model is used.

When you run a C or C++ program that uses the JNI Invocation API to run Java classes, ensure that the class path is set up correctly to enable the JVM to find your class files. If you modify the Java boot class path, include the SDK files that are necessary to run your applications.

To ensure that a JNI library exports the functions that a Java application must resolve at runtime, you can examine the library by using the nm tool. For example, a JNI library that is named libjnitest.so, and that contains JNI routines fooImpl and barImpl, must export the symbols:

$nm libjnitest.so
     255552 T Java_mypackage_SampleClass_fooImpl
     255528 T Java_mypackage_SampleClass_barImpl

For more information, see Compiler option defaults.

You can store native methods as follows:
Dynamic link libraries
On IBM Z® systems, JNI methods are typically stored in dynamic libraries called Dynamic Link Libraries (DLLs). DLLs contain functions and data, which can be referenced from another load module, for example a dynamic library or an executable program. Native methods are stored in DLLs and are either linked at build time, through the linking process, or at runtime, by dynamically loading the methods by using the IBM Z API dllload or the POSIX-compliant API dlopen. For more information about the dllload() and dlopen() functions, see Loading a DLL.

Programs can also link dynamically to shared libraries and shared objects, for example by using the dlopen() or dllload() families of subroutines. The JVM links in this way when it loads native libraries (for example, System.load(), System.loadLibrary(), Runtime.getRuntime().load(), Runtime.getRuntime().loadLibrary()).

For information about these subroutines, see dlopen() and dllload().

Note: To ensure that dynamic linking of native libraries works successfully you can, optionally, implement the lifecycle functions JNI_Onload() and JNI_OnUnload() in the library. If you have implemented JNI_Onload(), the native library must export it otherwise it is not visible to the runtime, and the JVM assumes that the library requires only the JNI version JNI_VERSION_1.1. If JNI_OnUnload() has been implemented, it must also be exported. If JNI_Onload() is implemented and exported, then the latest JNI version is returned; for example, JNI_VERSION_1.8.

Static linking in z/OS

You can link to JNI libraries statically, in addition to linking dynamically. Static libraries can be combined into the image of a custom launcher that launches a JVM process by using the invocation APIs.

Consider two static libraries: testlibA and testlibB. If you attempt to load the testlibA library in the Java program by using a command such as System.loadLibrary("testlibA"), the JVM first looks into the launching executable program's image for a routine named JNI_OnLoad_testlibA(). If this routine is found, the JVM uses this statically bound library to provide JNI definitions. If the routine is not found, the JVM falls back to load the testlibA library dynamically (for example libtestlibA.so) by looking in paths that are specified by -Djava.library.path (or LIBPATH).

On IBM Z systems, you must specify the following options when you build:
  • Wc,DLL, to ensure that the executable program is built as a DLL
  • Wc,EXPORTALL, to ensure that symbols in the executable program are exported and made available for look-up by shared libraries that the program loads
These options enable the launcher executable program to export symbols (such as JNI_Onload_testlibA()) so that the JVM can look them up before attempting dynamic linking.
The following example uses compilation and link lines to ensure that the static libraries testlibA and testlibB are linked with the launcher, which was built as a DLL, and exports all symbols.
cc -c -Wc,DLL,EXPORTALL launcher.c -o launcher.o
cc testlibA.o testlibB.o launcher.o -o launcher

Alternatively, you could remove EXPORTALL, in which case the program exports specific symbols by using #pragma export. For more information, see #pragma export.

Note: On IBM Z systems, an executable program must be built as a Dynamic Link Library (DLL) in addition to export symbols, if an executable program packages JNI routines that the Java program must reference, by using static linking. If an IBM Z executable program defines and exports JNI_OnLoad_testlibA, but is not itself built as a DLL (that is, -Wc,DLL is not specified), static linking is likely to fail, because the runtime is prevented from resolving the symbol back from the executable program.

The library initialization routine JNI_OnLoad_L, for a library L, must return JNI_VERSION_1_8(0x00010008).