Ejemplo de utilización de bibliotecas compartidas en z/OS

Este ejemplo describe el proceso de uso de bibliotecas compartidas nativas con una aplicación Java™ en sistemas z/OS.

Acerca de esta tarea

Esta tarea demuestra cómo crear una aplicación Java que carga e invoca funciones C dentro de una biblioteca nativa compartida.

Procedimiento

  1. Crear una aplicación de ejemplo ' Sample.java:
    public class Sample {
        /**
         * A static class initialization block that is run when this class
         * is first loaded. Here, try to load the target libSample.so shared library
         * that implements the printFromNative() method declared later.
         */
        static {
            try {
                System.loadLibrary("Sample");
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        }
        
        /**
         * Prints a message to STDOUT.
         * The 'native' keyword indicates that this method is implemented in native code,
         * callable through the Java Native Interface (JNI).
         */
        public static native void printFromNative();
    
        public static void main(String[] args) {
            // Invoke the native method
            Sample.printFromNative();
        }
    }

    Esta aplicación Java declara un método nativo estático ' Sample.printFromNative(), y llama a este método nativo desde el método ' main.

    Durante el bloque de inicialización de la clase estática que se ejecuta cuando la clase ' Sample ' se carga por primera vez, la llamada a ' System.loadLibrary("Sample") ' carga la biblioteca nativa de destino ' libSample.so.
    Nota: La API ' System.loadLibrary(libname) ' añade el prefijo ' lib y el sufijo ' .so ' al nombre de biblioteca que proporcione. El SDK busca la biblioteca compartida de destino dentro de la ruta de biblioteca especificada en la variable de entorno ' LIBPATH. Si su biblioteca compartida nativa de destino es un conjunto de datos MVS, o si tiene una ruta absoluta o un nombre de biblioteca específicos, utilice en su lugar la API ' System.load(filename) '.
  2. La parte Java de la aplicación se ha completado, por lo que ahora puede compilarla:
    javac Sample.java
  3. Utilice el mandato javac -h para crear un archivo de cabecera para el código nativo:
    javac -h . Sample.java
    Este comando genera un archivo de cabecera C que se llama ' Sample.h, con las firmas de método JNI apropiadas para la implementación de su aplicación nativa.
  4. Cree un archivo denominado Sample.c:
    #include <stdio.h>
    #include "Sample.h"
    
    JNIEXPORT void JNICALL Java_Sample_printFromNative(JNIEnv * env, jclass cls) {
      printf( "Printing from native\n" );
    }
    Este archivo proporciona la implementación nativa C del método Java Sample.printFromNative() .
  5. Compila ' Sample.c, lo enlaza, y lo enlaza en una librería compartida ' libSample.so, que puede ser cargada y llamada dinámicamente desde una aplicación Java. Puede utilizar el compilador XL C/C++ u Open XL C/C++.

    comando XL C/C++
    Por ejemplo:
    xlc -q64 -W "l,dll" -W "c,langlvl(extended),float(ieee),dll,exportall" -o libSample.so -I$JAVA_HOME/include -I$JAVA_HOME/include/zos Sample.c $JAVA_HOME/lib/j9vm/libjvm.x

    donde $JAVA_HOME es la vía de acceso JAVA_HOME de la instalación del SDK de IBM. El archivo de cabecera ' jni.h existe en ' $JAVA_HOME/include y ' libjvm.x ' está en ' $JAVA_HOME/lib/ 'j9vm.

    Los elementos específicos de ' XL C/C++ ' en los comandos de compilación y enlace son los siguientes:
    Tabla 1. Elementos específicos del comando XL C/C++
    Opción Descripción
    xlc El comando que ejecuta el compilador XL C.
    -q64 Opción válida sólo para 64 bits. Indica al compilador que compile la biblioteca compartida de destino para las plataformas AMODE64.
    -W "l,dll" La opción -W se pasa a la fase de enlace del compilador. El enlazador crea un archivo de biblioteca compartida ' .so.
    --W "c,langlvl(ampliado),
    float(ieee),
    dll,exportall"
    La opción -W se pasa a la fase de compilación del compilador.
    • langlvl(extended) habilita las extensiones de lenguaje que utilizan los archivos de cabecera JNI, como por ejemplo long long.
    • float(ieee) indica al compilador que genere números e instrucciones binarios de coma flotante IEEE754 , que coincidan con los tipos primitivos float y double del lenguaje Java.
    • dll indica al compilador que genere el código DLL. El código DLL puede exportar o importar funciones y variables externas.
    • exportall especifica que los programas externos pueden invocar las funciones de llamada de la biblioteca compartida.
    ComandoOpen XL C/C++
    Por ejemplo:
    ibm-clang -m64 -fvisibility=default -o libSample.so -I$JAVA_HOME/include -I$JAVA_HOME/include/zos Sample.c $JAVA_HOME/lib/j9vm/libjvm.x

    donde $JAVA_HOME es la ruta JAVA_HOME de su instalación de IBM SDK.

    Los elementos específicos de ' Open XL C/C++ ' en los comandos de compilación y enlace son los siguientes:
    Tabla 2. elementos específicos del comando Open XL C/C++
    Opción Descripción
    ibm-clang El comando que ejecuta el compilador Open XL C.
    -m64 Indica al compilador que compile la biblioteca compartida de destino para las plataformas AMODE64. sólo 64 bits.
    -fvisibility=por defecto Esta opción exporta todas las funciones y variables definidas externamente en la unidad de compilación para que una aplicación DLL pueda utilizarlas.
    El resto de elementos compartidos en los comandos de compilación y enlace son los siguientes:
    Tabla 3. Elementos comunes para XL y Open XL
    Opción Descripción
    -o libSample.so El archivo de salida, que es la biblioteca compartida que desea compilar. El nombre (el texto entre ' lib y ' .so) debe coincidir con el nombre que proporcionó a las API Java ' System.load(filename) o ' System.loadLibrary(filename).
    --I Indica al compilador que busque en el directorio $JAVA_HOME /include, además de en los directorios por defecto, archivos de cabecera (en este caso, archivos de cabecera JNI). Cambie $JAVA_HOME por la ruta JAVA_HOME de su instalación de IBM SDK.
    --I Indica al compilador que busque en el directorio $JAVA_HOME /include/zos, además de en los directorios por defecto, archivos de cabecera (en este caso, archivos de cabecera JNI).
    Sample.c El programa C.
    $JAVA_HOME/lib/j9vm/libjvm.x El archivo sidedeck que permite al código nativo enlazar y resolver las APIs JNI e Invocation.
  6. Ejecute la aplicación Sample .
    Dado que ha utilizado la API Java " System.loadLibrary " para especificar la biblioteca compartida de destino, debe asegurarse de que la variable de entorno " LIBPATH " o la propiedad " java.library.path " incluyen el directorio donde reside la biblioteca " libSample.so ".
    Por ejemplo:
    LIBPATH=. java Sample
    or
    java -Djava.library.path=. Sample
    El programa genera el siguiente mensaje:
    Printing from native

Resultados

Ahora, puede utilizar el mismo marco para acceder a bibliotecas compartidas nativas desde aplicaciones Java.