Inicio de cambios para el fixpack 35 de renovación de servicio 6

Utilización de código C o C++ nativo de 31 bits con la máquina virtual Java de 64 bits (soloz/OS )

A partir de la renovación de servicio 6, fixpack 35, puede volver a compilar el código C o C++ nativo de 31 bits y utilizarlo con una aplicación Java™ que se ejecute en una máquina virtual Java (VM) de 64 bits. Esta característica facilita la migración de aplicaciones Java que utilizan código nativo desde el SDK de 31 bits al SDK de 64 bits, con cambios mínimos en el código nativo.

Antes de empezar

Esta característica requiere el APAR PH28966 en z/OS® 2.3 o posterior.

Si el código JNI C o C++ de 31 bits utiliza almacenamientos intermedios de bytes directos, asegúrese de que el almacenamiento intermedio nativo esté asignado en el rango de memoria de 31 bits; de lo contrario, el código no podrá acceder a él. La función JNI GetDirectBufferAddress() comprueba si se ha llamado desde el código C o C++ de JNI que se ejecuta en modalidad de direccionamiento de 31 bits (AMODE 31). Si es así, la función devuelve la dirección de almacenamiento intermedio, si está en el rango de 31 bits, o null. Para crear un almacenamiento intermedio directo y asegurarse de que la memoria de almacenamiento intermedio nativa está en el rango de 31 bits, es posible que tenga que modificar el código C o C++ de la forma siguiente:
  1. Asigne la memoria de 31 bits utilizando la función adecuada. Si el código C o C++ se ejecutará en AMODE 31, utilice la función malloc() para asignar la memoria. Si el código C o C++ se ejecutará en AMODE 64, utilice la función __malloc31() para solicitar memoria en el rango de 31 bits.
  2. Cree el almacenamiento intermedio de bytes directos de Java que hace referencia a esta memoria de 31 bits pasando el almacenamiento intermedio en el parámetro de dirección de la función NewDirectByteBuffer() :
    jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity);
    Para obtener más información sobre esta función, consulte la documentación deOracle JNI.
  3. Realice un seguimiento del objeto ByteBuffer resultante. Cuando el objeto ya no sea utilizado por ningún método Java, libere la memoria de almacenamiento intermedio nativa. Este paso es necesario porque la JVM no libera la memoria de almacenamiento intermedio nativa cuando procesa el objeto ByteBuffer durante la recogida de basura.

Acerca de esta tarea

Es posible que desee migrar sus aplicaciones Java a la versión de 64 bits de IBM® SDK, Java Technology Edition para aprovechar el aumento de la capacidad de almacenamiento virtual (limitada a 2GB en el SDK de 31 bits). Por lo general, las aplicaciones Java que ejecutan código nativo de 31 bits solo pueden ejecutarse con un SDK de 31 bits; mezclar código de 31 bits y código de 64 bits en el mismo espacio de proceso es complicado debido a la incompatibilidad de los tamaños de los punteros y la direccionabilidad de la memoria entre estos dos tipos de código.

Con el APAR PH28966 en z/OS 2.3 y posterior, z/OS Language Environment® (LE) proporciona la posibilidad de ejecutar programas AMODE 31 y programas AMODE 64 en el mismo espacio de direcciones. Se establecen entornos LE separados para cada modalidad de direccionamiento (AMODE). El SDK de IBM aprovecha esta función para simplificar la migración de aplicaciones Java que utilizan código nativo de 31 bits al SDK de 64 bits. Las API de invocación y JNI del SDK de 64 bits permiten al código nativo de 31 bits compilar, enlazar e interoperar con el SDK de 64 bits. La máquina virtual de 64 bits también da soporte a la carga e invocación de bibliotecas y funciones nativas de 31 bits.

Como parte de esta característica, el SDK de 64 bits proporciona los archivos siguientes:
  • Conjunto compatible de 31 bits de archivos de cabecera JNI de C/C++, que contienen datos JNI y tipos de argumentos para dar soporte a las API de invocación y JNI. Estos archivos se encuentran en el directorio javahome/include31 , donde javahome es la vía de acceso JAVA_HOME de la instalación de IBM SDK. Los tipos JNI que representan referencias de objeto y otras construcciones de VM, como jobject, jarray, jclass, jmethodIDy jfieldID, se actualizan para que sean representaciones de 64 bits.
    Nota: Puesto que el lenguaje C no proporciona una forma de definir un tipo pointer de 64 bits en una aplicación de 31 bits, en su lugar se utiliza un tipo de datos long long primitivo de 64 bits. Esto puede dar lugar a avisos de compilador para el código que asigna o compara referencias de objeto JNI con NULL. Es posible que tenga que actualizar el código para asignar o comparar con 0 en su lugar.
  • Una biblioteca compartida de 31 bits, libjvm31.so, con un archivo de cubierta lateral libjvm31.x coincidente para habilitar el código nativo de 31 bits para enlazar y resolver las API de invocación y JNI.
Los pasos de alto nivel para utilizar esta característica son los siguientes:
  1. Vuelva a compilar cualquier código nativo C o C++ que haga referencia a las construcciones JNI en el conjunto include/jni31 de archivos de cabecera JNI y enlace con la biblioteca libjvm31.so.
  2. Ejecute la aplicación Java con el SDK de 64 bits, especificando la opción -XX:+Enable3164Interoperability VM.
Limitaciones:
  • La aplicación nativa de 31 bits debe ser una sola hebra. La aplicación Java de 64 bits puede ser multihilo, pero sólo se permite que un único hilo de aplicación Java interopere a través del límite AMODE. Si una segunda hebra de aplicación intenta cargar una biblioteca de 31 bits o llamar a una función C o C++ de 31 bits, normalmente se genera un java.lang.UnsatisfiedLinkError.
  • Debe compilar la aplicación nativa de 31 bits con el enlace CALL estándar; no se da soporte a XPLINK.
  • El soporte de manejo de condición de LE no está disponible en el límite de AMODE. Específicamente, no se da soporte a -XCEEHDLR, -Xsignal:userConditionHandler=percolate y las opciones relacionadas. Las condiciones LE no se convierten en excepciones Java.
  • El encadenamiento de señales no está soportado en el límite de AMODE.
  • Las variables de entorno solo se copian en el límite de AMODE en la primera transición. Las actualizaciones posteriores en un entorno AMODE no se propagan una a la otra; en lugar de esto, las variables se rastrean por separado en cada entorno AMODE. Para obtener más información, consulte Propagación de variables de entorno al Language Environment secundario en Introducción a los programas AMODE 31 y AMODE 64.

Procedimiento

  1. Vuelva a compilar el código C o C++ de 31 bits, enlácelo y enlácelo en una biblioteca compartida que se pueda cargar y llamar dinámicamente desde una aplicación Java que se ejecute con un IBM SDK de 64 bits.

    Debe establecer el directorio de inclusión JNI en $JAVA_HOME/include31 y utilizar el archivo de unidad lateral libjvm31.x del SDK de 64 bits. El código nativo debe compilarse con el enlace CALL estándar; no se da soporte a XPLINK. Por ejemplo, el mandato siguiente crea una biblioteca compartida denominada libSample.so para un programa C denominado Sample.c:

    XL C/C++
    xlc -W "l,dll" -W "c,langlvl(extended),float(ieee),dll,exportall" -o libSample.so  -I$JAVA_HOME/include31 Sample.c $JAVA_HOME/lib/s390x/j9vm/libjvm31.x
    donde $JAVA_HOME es la vía de acceso JAVA_HOME de la instalación del SDK de IBM.
    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
    Opción Descripción
    xlc El mandato que ejecuta el compilador C.
    -W "l,dll" La opción -W se pasa a la fase de vinculación del compilador. El enlazador crea un archivo .dll de biblioteca compartida. El enlace CALL estándar se utiliza de forma predeterminada para el código C o C++ de 31 bits.
    --W "c,
    langlvl(extendido)
    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.
    Open XL C/C++
    Tenga en cuenta que para las compilaciones de 31 bits se requiere Open XL 2.1. Open XL 1.1 no admite compilaciones de 31 bits.
    ibm-clang -fvisibility=default -o libSample.so  -I$JAVA_HOME/include31 Sample.c $JAVA_HOME/lib/s390x/j9vm/libjvm31.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. Open XL elementos específicos del comando
    Opción Descripción
    ibm-clang El comando que ejecuta el compilador Open XL C.
    -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.
    Elementos compartidos en los comandos de compilación y enlace
    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 ha utilizado en los métodos System.load(filename) o System.loadLibrary(libname) en la aplicación Java.
    -I$JAVA_HOME/include31 Indica al compilador que busque en el directorio $JAVA_HOME/include31 , además de los directorios predeterminados, los archivos de cabecera (en este caso, archivos de cabecera JNI especiales para ejecutar código nativo de 31 bits con el SDK de 64 bits). Cambie $JAVA_HOME por la ruta JAVA_HOME de su instalación de IBM SDK.
    Sample.c El programa C.
    $JAVA_HOME
    /lib/s390x/j9vm/libjvm31.x
    El archivo de cubierta lateral que habilita el código nativo de 31 bits para enlazar y resolver las API de invocación y JNI.
  2. Ejecute la aplicación Java en la máquina virtual de 64 bits, ya sea directamente en la línea de mandatos o desde una aplicación C o C++:
    Inicio de la máquina virtual desde la línea de mandatos
    • Especifique la opción de línea de mandatos -XX:+Enable3164Interoperability para habilitar las aplicaciones Java de 64 bits para cargar la biblioteca nativa de 31 bits e invocar los métodos implementados en ella.
    • Si su aplicación Java utiliza el método ' System.loadLibrary(libname) ', que no acepta una ruta, deberá especificar también la ubicación de su biblioteca compartida. Puede especificar la ubicación utilizando la opción de propiedad del sistema " -Djava.library.path " en la línea de comandos o utilizando la variable de entorno " LIBPATH.
    Por ejemplo:
    java -XX:+Enable3164Interoperability -Djava.library.path=. Sample
    Inicio de la máquina virtual desde una aplicación C o C++
    Si está utilizando la API de invocación de JNI_CreateJavaVM para crear una instancia de VM desde la aplicación C o C++, pase la opción -XX:+Enable3164Interoperability como argumento de VM.

Resultados

Ahora debería poder utilizar el código nativo de 31 bits existente de la aplicación Java que se ejecuta en la máquina virtual de 64 bits, y viceversa.
Si ve un mensaje de error similar al siguiente, compruebe que ha especificado la opción -XX:+Enable3164Interoperability en la línea de mandatos o en la API JNI_CreateJavaVM al ejecutar la aplicación:
An AMODE64 application is attempting to load an AMODE31 DLL load module.
Fin de los cambios para el fixpack 35 de renovación de servicio 6