출처 :http://www.hp.com/products1/unix/java/infolibrary/prog_guide/JNI_java2.html
Unless specified otherwise, the information in this chapter applies to both HP-UXPA-RISCand
HP-UX Itanium® Processor Family systems. Regarding the examples contained in this chapter, do not use +D64 with Java 1.3 based releases on Itanium. Beginning withSDK1.4.1 you may use +D64.
Table of contents | ||
» | Using Java 2 JNI on HP-UX | |
» | Support for C++ applications built with -AA options (PA-RISC) | |
» | DereferencingNULLpointers | |
» | Using Native Methods on HP-UX | |
» | Java calling a native (non-Java) method | |
» | Sample code for SDK 1.3.1 | |
» | Sample Java calling native method implementation in C | |
» | Sample Java calling native method implementation in HP aC++ | |
» | Native (non-Java) calling Java methods |
» | Sample code for SDK 1.3.1 | |
» | Sample native calling Java implementation in C | |
» | Sample native calling Java implementation in HP aC++ | |
The Java Native Interface, typically referred to as JNI, is a standard native method interface that allows Java to call up native libraries written in other languages. It also allows you to load theJVMinto native applications to integrate Java functionality into native applications. JNI offers a JVM-independent programming interface to native programs which enables developers to write a single native method library version that will be binary compatible with all JVMs on a given platform.
<applicationdirectory>/lib/<architecturedirectory>
<applicationdirectory>/lib/<architecturedirectory>native_threads/foo.sl
The HP-UX implementation of JNI does not differ significantly from that of the JavaSoft implementation on Solaris. Refer to JavaSoft's JNI documentation listings at:http://onesearch.sun.com/search/developers/index.jsp?qt=JNI&uid=6910018
Support for C++ applications built with-AAand-APoptions (PA-RISC)
Java supports the-AAand-APoptions to build your C++ product. On Itanium systems, the C++ runtime libraries support-AAand-APby default. On HP-UX 11.0 or 11.11 PA-RISC, if you are using the ANSI Standard C++ runtime (-AA) option in an application that loads Java, you need to use the-AAversion oflibjvmandlibfontmanager. Note that these libraries are provided as a separate download on the same page from where you download the SDK and RTE, starting at this webpage:
http://www.hp.com/products1/unix/java/java2/sdkrte14/index.html
These are the Standard C++ Runtime version of these libraries:
Note:The default stack size for 1.4 and 5.0 64-bit mode threads created by the JVM is 1MB. On PA-RISC 32 and 64-bit systems, the default stack size is 64KB. Therefore, if you are using C language main programs that attach with JNI, for threads created using the pthread library, you will want to adjust the stack size to avoid overflows. For further details on thread Stack Size Limits, refer to "Main/primordial thread stack size limits" and "Non-Main/primordial thread stack size limits".
Java calling a native (non-Java) method
native void sample(int x, int y);
All Java native methods must reside in a shared library. This implies that the native methods must be built using the+zor+Zcompiler options. These options cause the compiler to generatePIC(Position-Independent-Code). The shared library containing the native method implementation is dynamically loaded during execution of the Java program using the Java method:
System.loadLibrary(). The implementation of this function with the JVM on HP-UX relies upon the HP-UX runtime routineshl_load.
-D_HPUX -D_POSIX_C_SOURCE=199506L
Sample Java calling native method implementation in C
Here is the sample Java program that calls a native method, which has a C implementation:
$ <java_dir>/bin/javac -verbose TestJava2CallingNative.java
$ <java_dir>/bin/javah -verbose -jni TestJava2CallingNative
Here is the sample C native method implementation for sayHelloWorld:
To compile this C source file:
Create the shared library containing the native method implementation:
PA-RISC:
$ aCC -b -o libaCCImpl.sl aCCImpl.o \
-lstd -lstream -lCsup -lm
(see below for Itanium)
libcImpl.sl
(libcImpl.so on Itanium)
To execute the Java program, you must set theSHLIB_PATHenvironment variable to contain the location of the directory that containslibcImpl.sl(libcImpl.soonIPF).SHLIB_PATHis the HP-UX name forLD_LIBRARY_PATHand can contain a list of directories each separated by colons.
Sample Java calling native method implementation in HP aC++
Here is a sample Java program that calls a native method which has a C++ implementation. This C++ example will use the aC++ compiler. HP has two different C++ compilers, and older cfront based product and a newer aC++ compiler. You can tell which C++ compiler you are using by the name of the driver. The older cfront based product uses CC as the driver, while the newer aC++ compiler uses aCC as the name of the driver. The official HP product names for these two C++ compilers are HP C++ for the cfront based product and HP aC++ for the new C++ compiler.
(Note: In the HP-UXSDK, for the Java 2 Platform there is support for the HP aC++ compiler, but not for the older cfront HP C++ compiler. Since the HP-UX SDK, for the Java 2 Platform contains C++ libraries built with the HP aC++ compiler, any user shared libraries compiled with cfront are not compatible. Therefore, you have to recompile your shared libraries with HP aC++ if you intend to use them with the HP-UX SDK for the Java 2 Platform.)
//
// TestJava2CallingNative.java
//
class TestJava2CallingNative {
The code above is very similar to the code in the C-based example; the only differences are the addition of the declaration and invocation of the native methodinitialize(). With the PA-RISC version of HP aC++ some internal C++ runtime data structures need to be initialized before transferring control to any C++ code. Theinitialize()method will perform the necessary initialization. With the Itanium version of HP aC++ this initialization step is no longer needed and theinitialize()method can be omitted.
Compile this class:
$ <java_dir>/bin/javac -verbose TestJava2CallingNative.java
Output:
TestJava2CallingNative.class
Generate the JNI header file for this class. You must have the current directory in yourCLASSPATHfor the javah command to find your newly compiled class file.
$ <java_dir>/bin/javah -verbose -jni TestJava2CallingNative
Output:
TestJava2CallingNative.h
Here is the sample C++ native method implementation for initialize and sayHelloWorld:
//
// File aCCImpl.C
//
#include "TestJava2CallingNative.h"
#include <iostream.h>
extern "C" {
void _main();
}
JNIEXPORT void JNICALL
Java_TestJava2CallingNative_initialize(JNIEnv *, jclass)
{
_main();
}
JNIEXPORT void JNICALL
Java_TestJava2CallingNative_sayHelloWorld(JNIEnv *, jclass)
{
cout << "aC++ says HelloWorld via iostreams"
<< endl;
}
In the above example you can see the additional native methodinitialize()simply calls the routine_main(). Since the Java Native interface does not allow us to call a routine name_maindirectly we have to write this wrapper function to allow us to call_mainindirectly. Also note that we need to useinitialization extern "C"to direct the C++ compiler not to perform name mangling on this routine. The entry point_mainis located in the PA-RISC version of the C++ runtime support librarylibCsup.sl.
Note:As mentioned above the additional initialization step is no longer necessary with the Itanium version of HP aC++. In fact calling _main from code compiled by the Itanium version of HP aC++ will result in_mainbeing an unresolved symbol.
Compile this C++ source file:
$ aCC +z +u4 -c -D_HPUX -D_POSIX_C_SOURCE=199506L
-I<java_dir>/include -I<java_dir>/include/hp-ux \
aCCImpl.C
Output:
aCCImpl.o
Create the shared library containing the native method implementation:
PA-RISC:
$ aCC -b -o libaCCImpl.sl aCCImpl.o \
-lstd -lstream -lCsup -lm
(see below for Itanium)
Output:
libaCCImpl.sl
(libaCCImpl.so on Itanium)
Note that the C++ driver program aCC must be used to create the shared library. Also note that an explicit dependency on three C++ runtime libraries need to be specified. The HP aC++ compiler has split the runtime support libraries into three separate shared libraries:libCsup.sl, libstream.slandlibstd.sl(libCsup.so, libstream.soandlibstd.soon Itanium).
All HP aC++ programs requirelibCsup.sl(libCsup.soon Itanium). The other two libraries are required by a subset of C++ programs. In this example, we could omitlibstd.slon PA since we are not using the Standard Template Library functionality. However it is usually best to link your native method shared library against all three of these libraries.
On Itanium, create the shared library using:
$ aCC -b -o libaCCImpl.so aCCImpl.o \
-lstd_v2 -lCsup -lunwind -lm
On Itanium,-lstd_v2is necessary, otherwise, running the program will result inUnsatisfiedLinkErrors.
Linking a shared library against these other shared libraries will cause the linker to record the fact that wheneverlibaCCImpl.sl(orlibaCCImpl.so) is loaded into memory the dependent librarieslibCsup.sl, libstream.slandlibstd.sl, (libCsup.so, libstream.soandlibstd.soon Itanium) also must be loaded. This is necessary sincelibCsup.sl(orlibCsup.so) contains the entry-point_mainas well as all the other necessary runtime support routines required by every C++ method.
To execute the Java program, you must set theSHLIB_PATHenvironment variable to contain the location of the directory that includeslibaCCImpl.sl(libaCCImpl.soon Itanium).SHLIB_PATHis the HP-UX name forLD_LIBRARY_PATHand can contain a list of directories each separated by colons.
$ export SHLIB_PATH=.:$SHLIB_PATH
$ <java_dir>/java TestJava2CallingNative aCCImpl
Library aCCImpl successfully loaded
initialize C++ runtime
Calling sayHelloWorld
ANSI C++ says HelloWorld via iostreams
All done
Native (non-Java) calling Java methods
In Java 2, the Java Virtual Machine (JVM) is shipped as a shared library. To utilize the JVM in a native application you must link the application againstlibjvm.sl(libjvm.soon Itanium). The JNI supports an InvocationAPIthat allows you to create and initialize a new JVM. Using this newly created JVM you can invoke various Java methods, create new Java objects or access Java objects created by the JVM.
The InvocationAPIis provided by the C/C++ header filejni.h. It actually provides two different interfaces. It provides a standard C interface and an object based C++ interface.
Here is the sample Java class that we will call from C and C++ programs:
Compile the above Java file into byte code:
$ <java_dir>/bin/javac -verbose TestNonJavaCallingJava2.java
Sample native calling Java implementation in C
Here is the sample C program. This program will use the JVM Invocation Interface to create a new JVM, find a class namedTestNonJavaCallingJava2, and find a Java method namedprintInt, and invoke the method with an argument of 100.
options[0].optionString = (char *) \
"-Djava.class.path=.";
vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
vm_args.nOptions = 1;
vm_args.ignoreUnrecognized = JNI_FALSE;
/*
* The CLASSPATH environment variable does not
* set the classpath for JNI applications that
* have a native main program. This behavior
* is consistent with the JavaSoft reference platform.
*/
/*
* load and initialize a java vm,
* return a JNI interface ptr in env
*/
res = JNI_CreateJavaVM(&jvm,(void **)&env,&vm_args);
if (res != 0) {
printf("JNI_CreateJavaVM failed. %d\n", res);
exit(1);
}
jni = *env;
vmi = *jvm;
// Find the class
jclass cls = jni->FindClass(env, "TestNonJavaCallingJava2");
if (cls == 0) {
printf("Could not locate class NonJavaCallingJava2");
exit(1);
}
// Find the method
jmethodID mid = jni->GetStaticMethodID(env, cls, "printInt", "(I)V");
if (mid == 0) {
printf("Could not locate method printInt with signature (I)V");
exit(1);
}
// Invoke the method
jni->CallStaticVoidMethod(env, cls, mid, 100);
// we are done
vmi->DestroyJavaVM(jvm);
}
Compile the C source file:
$ cc -O -c -Ae +u4 -D_HPUX -D_POSIX_C_SOURCE=199506L \
-I<java_dir>/include -I<java_dir>/include/hp-ux c_main.c
Output:
c_main.o
Link the main executable.
cc -z -o c_main c_main.o \
-L<java_dir>/jre/lib/PA_RISC2.0/hotspot \
-ljvm -lpthread -llwp
On Itanium, the command to the main program would look like this:
$ cc -z -o cmain cmain.o \
-L<java_dir>/jre/lib/IA64/hotspot \
-ljvm -lpthread
Output:
c_main
Notes:
- If you are using SDK 1.2 or 1.3 and your C main is linkedEXEC_MAGICso as to be able to address more than 1GBof private data, you must use the Hotspot JVM, or use the Classic JVM with the
"-nojit" option. TheJITcompiler in Classic 1.2 and 1.3 is not compatible withEXEC_MAGIC.
To access Itanium libraries, change PA_RISC2.0 to IA64.
Sample native calling Java implementation in HP aC++
Here is the sample HP aC++ program. This program will use the C++ object-oriented interface provided in the JVM Invocation Interface to create a new JVM, find a class namedTestNonJavaCallingJava2, and find a Java method namedprintInt, and invoke the method with an argument of 100.
Create the main program and link:
$ aCC -z -o aCC_main aCC_main.o \
-L<java_dir>/jre/lib/PA_RISC2.0/hotspot \
-ljvm -lpthread -llwp
Main/Primordial thread stack size limits
-XX:MainThreadStackSize=n
-Xss[n][k or m]
An irrecoverable stack overflow has occurred.
Current Java thread:
"main" prio=7 tid=4000a1b8 nid=1 lwp_id=127233 runnable [0x00000000..0x6fff0b08]
/opt/java1.4/jre/lib/PA_RISC2.0/server/libjvm.sl
[...]
- Use the option-XX:MainThreadStackSize=<value>to increase the primordial thread stack size, However be aware that -XXoptions are non-standard options, and are liable to change from release to release.
- Use the-Xssoption to set the thread stack size. This workaround may be less desirable because-Xsssets the stack size for all threads, not just the primordial thread. For example, if your application has 100 threads and you set the maximum thread stack size to 4M with the-Xssoption, the application would use nearly 400MB of address space just for thread stacks. If you did not use the-Xssoption, the application would have only used 50MB (512k (the default-Xssvalue) * 100 threads) of address and swap space.
- Change the application so as to CallJNI_CreateJavaVM()from a non primordial thread. That is, create a new thread with an appropriate stack size, usingpthread_create()and use this new thread to initialise the JVM.
Non-Main/Primordial thread stack size limits
- If the thread is created in native code and is attached to Java throughJNI_AttachCurrentThread, increase the stack size attribute when creating the thread withpthread_create.
- If the thread is created inside Java and there is a stack overflow condition, increase the thread stack size with-Xss<n>
Dynamically loading the Hotspot JVM (SDK 1.3.1.x and 1.4.2.x PA-RISC)
(The example for Dynamically loading the Classic JRE can now be found in theAppendix.)
#include <jni.h>#include <stdlib.h>#include <dl.h>typedef int (*JNI_CreateJavaVM_t)(JavaVM**, void**, void*);int main(){ JNIEnv *env; JavaVM *jvm; JNIEnv jni; JavaVM vmi; JavaVMInitArgs vm_args; JavaVMOption options[4]; jint res; printf ("beginning execution...\n"); options[0].optionString = (char *) "-Djava.class.path=."; /* user classes */ vm_args.version = JNI_VERSION_1_2; vm_args.options = options; vm_args.nOptions = 1; vm_args.ignoreUnrecognized = JNI_FALSE; // load libjvm.sl (PA-RISC) or libjvm.so (Itanium) shl_t libsym = shl_load("libjvm.sl", BIND_IMMEDIATE|DYNAMIC_PATH, 0L); if (libsym == 0) { fprintf(stderr, "Unable to shl_load libjvm.sl\n"); exit (1); } else fprintf(stdout, "shl_loaded libjvm.sl successfully!\n"); // find function JNI_CreateJavaVM JNI_CreateJavaVM_t func = NULL; res = shl_findsym(&libsym, "JNI_CreateJavaVM", TYPE_PROCEDURE, &func); if (res == 0) fprintf(stdout, "Found symbol JNI_CreateJavaVM!\n"); else { fprintf(stderr, "Unable to find symbol JNI_CreateJavaVM!\n"); exit (1); } // load and init a java vm, return a JNI interface ptr in env printf ("before CreateJavaVM\n"); res = (*func)(&jvm, (void **)&env, (void *)&vm_args); if (res != 0) { fprintf (stderr, "JNI_CreateJavaVM failed. %d\n", res); exit (1); } else fprintf (stdout, "after CreateJavaVM \n"); jni = *env; vmi = *jvm; // find the class fprintf (stdout, "before FindClass\n"); jclass cls=env->FindClass("TestNonJavaCallingJava2"); if (cls == 0) { fprintf (stderr, "Could not locate class TestNonJavaCallingJava2 in classpath %s\n", options[0].optionString); exit(1); } else fprintf (stdout, "after FindClass\n");// find the methodjmethodID mid=env->GetStaticMethodID(cls, "printInt", "(I)V");if (mid == 0) {fprintf (stderr, "Could not locate method printInt with signature (I)V in theclass TestNonJavaCallingJava.");exit(1);}else fprintf (stdout, "after GetStaticMethod\n");fflush (stdout); // invoke the methodenv->CallStaticVoidMethod(cls, mid, 100);// we are donejvm->DestroyJavaVM();} To compile the program:aCC --c loadjava.cpp -mt -ext -D_HPUX -D_POSIX_C_SOURCE=199506L \ -I<java_dir>/include -I<java_dir>/include/hp-ux Linking the program:To link the program onPA-RISC:aCC -z -mt -o loadjava loadjava.o -lpthreadTo link the program onItanium:aCC -z -mt -o loadjava loadjava.o -lpthread# allow use of SHLIB_PATH to locate shared libraries required by program
chatr +s enable loadjavaTo execute the program, set environment variables. The example is forPA-RISC. ForItaniumSDK 1.3.1.x, substitute IA64 for PA_RISC2.0 in the command below. ForItaniumSDK 1.4.2.x substitute IA64N for PA_RISC2.0 in the command below.export SHLIB_PATH=$JAVA_HOME/jre/lib/PA_RISC2.0/hotspot:$JAVA_HOME/jre/lib/PA_RISC2.0export CLASSPATH=. (Note: we are using the same TestNonJavaCallingJava2.class from prior examples)# Run program# Use JAVA_PRELOAD_ONCE if want to dynamically load library with TLS (e.g. HotSpot). For Itanium,substitute IA64 or IA64N for PA_RIS2.0, and substitute libjvm.so for libjvm.slJAVA_PRELOAD_ONCE=$JAVA_HOME/jre/lib/PA_RISC2.0/hotspot/libjvm.sl ./loadjava# Output:#TestNonJavaCallingJava.printInt received: 100
» | Java Native Interface: Programmer's Guide and Specification by Sheng Liang |
» | Please let us know additional information you'd like to see in the programmer's guide. |
Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems,Inc. in theU.S.and other countries. Hewlett-Packard is independent of Sun Microsystems, Inc
'Java' 카테고리의 다른 글
Java™ Troubleshooting Guide for HP-UX Systems (0) | 2007.04.03 |
---|---|
Java SE Application Design With MVC (0) | 2007.03.24 |
Using VC++ components from Java program (0) | 2007.03.23 |