JNI runtime linking
The Java™ Native Interface (JNI) enables runtime linking to dynamic and static native libraries.
Information specific to AIX systems
For runtime linking, applications can be linked by using the -brtl loader option. 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 AIX
cc_r -qmkshrobj [-qarch=ppc | -q64] -Ijava_install_dir/include
-o libnm.a nm.c
The -qmkshrobj
option disables runtime linking. For more
information about shared object files, runtime linking, and the use of cc
and
ld
command-line options, see: - Developing and Porting C and C++ Applications on AIX at http://www.redbooks.ibm.com/abstracts/sg245674.html
- The C and C++ compiler website at https://www.ibm.com/marketplace/ibm-c-and-c-plus-plus-compiler-family
- The AIX online documentation at https://www.ibm.com/support/knowledgecenter/ssw_aix/welcome
Before you run a Java program that uses native methods, ensure that LIBPATH contains the list of directories that hold the shared objects for the native methods. For more information about building AIX shared objects, see C and C++ Application Development on AIX . Go to https://www.ibm.com/redbooks and search for "SG245674".
If you set the setuid or setgid attribute on JNI native code programs, that setting changes the effective LIBPATH environment variable. This change might cause unexpected or incorrect behavior with those programs. For more information about this usage, see Developing and Porting C and C++ Applications on AIX at http://www.redbooks.ibm.com/abstracts/sg245674.html, section 2.3.3.
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/jre/lib and java_install_dir/jre/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 a C program (invAPITest.c) that uses the JNI Invocation API:
cc_r [-qarch=pwr4 | -q64] -Ijava_install_dir/include
-o invAPITest
-L/usr/lib
-L/lib
-Ljava_install_dir/jre/lib/j9vm
-Ljava_install_dir/jre/lib
-ljvm invAPITest.c
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 determine whether a C or C++ program that is using the JNI Invocation API was built with the -bM:UR option, use the following command:
dump [-X64] -ov <program name>
Output similar to the following is generated:
>dump -X64 -ov <program name>
***Object Module Header***
# Sections Symbol Ptr # Symbols Opt Hdr Len Flags
4 0x0001a728 1305 120 0x1002
Flags=( EXEC DYNLOAD DEP_SYSTEM )
Timestamp = "14 Oct 03:26:43 2005"
Magic = 0x1f7 (64-bit XCOFF)
***Optional Header***
Tsize Dsize Bsize Tstart Dstart
0x000127f8 0x00001b80 0x00000470 0x1000001f8 0x1100009f0
SNloader SNentry SNtext SNtoc SNdata
0x0004 0x0002 0x0001 0x0002 0x0002
TXTalign DATAalign TOC vstamp entry
0x0005 0x0003 0x110002158 0x0001 0x110002040
maxSTACK maxDATA SNbss magic modtype
0x00000000 0x00000000 0x0003 0x010b UR
-bM:UR
binder option. For example:
export LDR_CNTRL=USERREGS
If you need to specify multiple options with LDR_CNTRL, separate those options with the @ symbol.
export AIXTHREAD_SCOPE=S
Another option is to preset the thread's scope attribute to
PTHREAD_SCOPE_SYSTEM by using the AIX
pthread_attr_setscope
function when the thread is created.
- Shared object
- A shared object is a single object file that has the SRE (Shared REusable) bit set in the XCOFF header. The SRE bit tells the linker that this file is linked dynamically. These files typically have a name of the form <filename> .o, but they can also be named lib<name> .a to allow the linker to search for them with the -lname option; but these are not archive library files.
- Shared library
- A shared library is an "ar" format archive library in which one or more of the archive members is a shared object. Note that this library can also contain non-shared object files that are statically linked. A shared library has the name in the form lib<name> .a. This form allows the linker to search for libraries with the -lname option.
For more information, see the AIX documentation.
Programs can also link dynamically to shared libraries and shared objects, for example by using the dlopen() family 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 dlopen see dlopen Subroutine.
For information about AIX loading and linking mechanisms, see AIX Linking and Loading Mechanisms.
System.loadLibrary("<library>(<member>)")
where
<library> is the name of the shared library archive and
<member> is the name of an archive member. For example:
System.loadLibrary("libShared.a(libSample.o)")
Static linking in AIX
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 AIX, in addition to enabling the runtime linking by specifying -brtl, you must build with the option -bexpall specified. This process ensures that the launcher exports symbols (such as JNI_OnLoad_testlibA()) and also allows shared libraries that are loaded by the executable program (such as that of the JVM) to look up the symbols. For the JVM to statically link, it must be able to look back into the executable program before any attempt at dynamic linking.
$ cc_r -qpic -brtl -bexpall -brtl testlibA.o testlibB.o -o <launcher>
where <launcher> is the name of an executable program that contains the
images of the testlibA and testlibB libraries, as well as being a Java launcher that launches a JVM through the invocation APIs. The library initialization routine JNI_OnLoad_L, for a library L, must return JNI_VERSION_1_8(0x00010008).
Information specific to Linux 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 Linux
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/jre/lib and java_install_dir/jre/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 a C program (invAPITest.c) that uses the JNI Invocation API:
cc [-m32|-m64] -Ijava_install_dir/include
-o invAPITest
-L/usr/lib
-L/lib
-Ljava_install_dir/jre/lib/j9vm
-Ljava_install_dir/jre/lib
-ljvm invAPITest.c
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 named libjnitest.so that
contains JNI routines fooImpl
and barImpl
must export the
following symbols:
$ nm libjnitest.so
000537d0 T Java_mypackage_SampleClass_fooImpl
0004f020 T Java_mypackage_SampleClass_barImpl
Similarly, the command objdump -T lists the exported symbols in a shared library:
000537d0 g DF .text 00000040 Base 0x60
Java_mypackage_SampleClass_fooImpl
0004f020 g DF .text 00000254 Base 0x60
Java_mypackage_SampleClass_barImpl
- Shared library
- A shared library (or shared object) on Linux is a dynamically linking library that can be linked against at build time (link-time linking) or at run time (runtime linking). Whereas link-time linking against a shared library is accomplished by using the linker-editor tool ld , runtime linking uses the dlopen(3) family of functions.
Programs can also link dynamically to shared libraries and shared objects, for example by using the dlopen() family 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 dlopen(3), see the Linux man documentation and search for dlopen.
Static linking in Linux
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
LD_LIBRARY_PATH).
On Linux, you must build with the option -rdynamic specified to ensure that the launcher exports symbols (such as JNI_OnLoad_testlibA()) and also allows shared libraries that are loaded by the executable program (such as that of the JVM) to look up the symbols. For the JVM to statically link, it must be able to look back into the executable program before any attempt at dynamic linking. Without -rdynamic, non-static symbols are still exported from the executable program, but are not visible to shared libraries that are loaded by the program. The following example shows the usage of -rdynamic:
$ cc -rdynamic testlibA.o testlibB.o -o <launcher>
The library initialization routine JNI_OnLoad_L, for a library L, must return JNI_VERSION_1_8(0x00010008).
Information specific to Windows 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 Windows
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 linker option /link /LIBPATH
to do the following task:
- Add your Java java_install_dir\jre\bin\ and java_install_dir\jre\bin\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 jvm.dll (by using the -ljvm option).
On Windows, no special options are required for the command-line compiler cl.exe. Generally, a Microsoft compiler is used, for example VC++. For more information about compiler options, see the documentation for the compiler that is being used. By default, VC++ picks libraries that are present in the environment variable %LIB%. The variable must always point at the \lib subdirectory of the VC++ SDK as one of the search paths for linking libraries.
cl.exe /I java_install_dir\jre\include
/FeinvAPITest
invAPITest.c
/link /LIBPATH:java_install_dir\jre\bin\j9vm
/LIBPATH:java_install_dir\jre\bin
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.
C:\>dumpbin.exe /EXPORTS jnitest.dll
Dump of file jnitest.dll
File Type: DLL
Section contains the following exports for JNITEST.dll
00000000 characteristics
5412A472 time date stamp Fri Sep 12 03:44:50 2014
0.00 version
1 ordinal base
5 number of functions
5 number of names
ordinal hint RVA name
...
1 27 0000CE10 Java_mypackage_SampleClass_fooImpl = Java_mypackage_SampleClass_fooImpl
2 28 000085A0 Java_mypackage_SampleClass_barImpl = Java_mypackage_SampleClass_barImpl
...
For more information on dumpbin.exe and its options, see the MSDN documentation.
- Dynamic link libraries
- On Windows, 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 Windows API LoadLibrary() and LoadLibraryEx() functions. For more information about the LoadLibrary() family of functions, refer to the MSDN documentation.
Static linking in Windows
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 testlibA.dll) by
looking in paths that are specified by -Djava.library.path (or
PATH).
Windows does not impose any special options to be specified while you build a launcher executable program.
The library initialization routine JNI_OnLoad_L, for a library L, must return JNI_VERSION_1_8(0x00010008).
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/jre/lib and java_install_dir/jre/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/jre/include
-o invAPITest
-L/usr/lib
-L/lib
-Ljava_install_dir/jre/lib/j9vm
-Ljava_install_dir/jre/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.
- 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().
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).
-
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
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.
The library initialization routine JNI_OnLoad_L, for a library L, must return JNI_VERSION_1_8(0x00010008).