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.

Nota: QJVAJNI64 es un programa de servicio para el método nativo teraspace/LLP64 y el soporte de API de invocación.

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

Nota: Al utilizar los ejemplos de código, acepta los términos de la Información de licencia y exención de responsabilidad de código.
#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.