Ejemplo: API de invocación Java
Este ejemplo C de ILE (entorno de lenguaje integrado) sigue el paradigma de la API de invocación estándar.
Hace lo siguiente:
- Crea una máquina virtual Java™ utilizando
JNI_CreateJavaVM(). - Utiliza la máquina virtual Java para buscar el archivo de clase que desea ejecutar.
- Se busca el ID del método main de la clase.
- Se llama al método main de la clase.
- Se notifican los errores si se produce una excepción.
Al
crear el programa, el programa de servicio
QJVAJNI o QJVAJNI64 proporciona la función de API
JNI_CreateJavaVM(). JNI_CreateJavaVM() crea la máquina virtual Java.
Estos programas de servicio residen en el directorio de enlace del sistema y no es necesario identificarlos explícitamente en un mandato crear de lenguaje de control (CL). Por ejemplo, no identificaría explícitamente los programas de servicio mencionados anteriormente al utilizar el mandato Crear programa (CRTPGM) o el mandato Crear programa de servicio (CRTSRVPGM).
Una manera de ejecutar este programa es utilizar el siguiente mandato de lenguaje de control:
SBMJOB CMD(CALL PGM(YOURLIB/PGMNAME)) ALWMLTTHD(*YES)Cualquier trabajo que cree una máquina virtual Java debe tener capacidad multihebra. La salida del programa principal, así como cualquier salida del programa, va a parar a los archivos en spool QPRINT. Estos archivos en spool resultan visibles si se utiliza el mandato de lenguaje de control (CL) Trabajar con trabajos sometidos (WRKSBMJOB) y se visualiza el trabajo iniciado utilizando el mandato CL Someter trabajo (SBMJOB).
Ejemplo: Utilización de la API de invocación de Java en ILE C
#define OS400_JVM_12
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <jni.h>
/* Specify the pragma that causes all literal strings in the
* source code to be stored in ASCII (which, for the strings
* used, is equivalent to UTF-8)
*/
#pragma convert(819)
/* Procedure: Oops
*
* Description: Helper routine that is called when a JNI function
* returns a zero value, indicating a serious error.
* This routine reports the exception to stderr and
* ends the JVM abruptly with a call to FatalError.
*
* Parameters: env -- JNIEnv* to use for JNI calls
* msg -- char* pointing to error description in UTF-8
*
* Note: Control does not return after the call to FatalError
* and it does not return from this procedure.
*/
void Oops(JNIEnv* env, char *msg) {
if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
}
(*env)->FatalError(env, msg);
}
/* This is the program's "main" routine. */
int main (int argc, char *argv[])
{
JavaVMInitArgs initArgs; /* Virtual Machine (VM) initialization structure, passed by
* reference to JNI_CreateJavaVM(). See jni.h for details
*/
JavaVM* myJVM; /* JavaVM pointer set by call to JNI_CreateJavaVM */
JNIEnv* myEnv; /* JNIEnv pointer set by call to JNI_CreateJavaVM */
char* myClasspath; /* Changeable classpath 'string' */
jclass myClass; /* The class to call, 'NativeHello'. */
jmethodID mainID; /* The method ID of its 'main' routine. */
jclass stringClass; /* Needed to create the String[] arg for main */
jobjectArray args; /* The String[] itself */
JavaVMOption options[1]; /* Options array -- use options to set classpath */
int fd0, fd1, fd2; /* file descriptors for IO */
/* Open the file descriptors so that IO works. */
fd0 = open("/dev/null", O_CREAT|O_TRUNC|O_RDWR, S_IRUSR|S_IROTH);
fd1 = open("/dev/null", O_CREAT|O_TRUNC|O_WRONLY, S_IWUSR|S_IWOTH);
fd2 = open("/dev/null", O_CREAT|O_TRUNC|O_WRONLY, S_IWUSR|S_IWOTH);
/* Set the version field of the initialization arguments for JNI v1.4. */
initArgs.version = 0x00010004;
/* Now, you want to specify the directory for the class to run in the classpath.
* with Java2, classpath is passed in as an option.
* Note: You must specify the directory name in UTF-8 format. So, you wrap
* blocks of code in #pragma convert statements.
*/
options[0].optionString="-Djava.class.path=/CrtJvmExample";
initArgs.options=options; /* Pass in the classpath that has been set up. */
initArgs.nOptions = 1; /* Pass in classpath and version options */
/* Create the JVM -- a nonzero return code indicates there was
* an error. Drop back into EBCDIC and write a message to stderr
* before exiting the program.
* Note: This will run the default JVM and JDK which is 32bit JDK 6.0.
* If you want to run a different JVM and JDK, set the JAVA_HOME environment
* variable to the home directory of the JVM you want to use
* (prior to the CreateJavaVM() call).
*/
if (JNI_CreateJavaVM(&myJVM, (void **)&myEnv, (void *)&initArgs)) {
#pragma convert(0)
fprintf(stderr, "Failed to create the JVM\n");
#pragma convert(819)
exit(1);
}
/* Use the newly created JVM to find the example class,
* called 'NativeHello'.
*/
myClass = (*myEnv)->FindClass(myEnv, "NativeHello");
if (! myClass) {
Oops(myEnv, "Failed to find class 'NativeHello'");
}
/* Now, get the method identifier for the 'main' entry point
* of the class.
* Note: The signature of 'main' is always the same for any
* class called by the following java command:
* "main" , "([Ljava/lang/String;)V"
*/
mainID = (*myEnv)->GetStaticMethodID(myEnv,myClass,"main",
"([Ljava/lang/String;)V");
if (! mainID) {
Oops(myEnv, "Failed to find jmethodID of 'main'");
}
/* Get the jclass for String to create the array
* of String to pass to 'main'.
*/
stringClass = (*myEnv)->FindClass(myEnv, "java/lang/String");
if (! stringClass) {
Oops(myEnv, "Failed to find java/lang/String");
}
/* Now, you need to create an empty array of strings,
* since main requires such an array as a parameter.
*/
args = (*myEnv)->NewObjectArray(myEnv,0,stringClass,0);
if (! args) {
Oops(myEnv, "Failed to create args array");
}
/* Now, you have the methodID of main and the class, so you can
* call the main method.
*/
(*myEnv)->CallStaticVoidMethod(myEnv,myClass,mainID,args);
/* Check for errors. */
if ((*myEnv)->ExceptionOccurred(myEnv)) {
(*myEnv)->ExceptionDescribe(myEnv);
}
/* Finally, destroy the JavaVM that you created. */
(*myJVM)->DestroyJavaVM(myJVM);
/* All done. */
return 0;
}Para obtener más información, consulte API de invocación de Java.