Enlace de tiempo de ejecución JNI
JNI (Java™ Native Interface) habilita el enlace en tiempo de ejecución a bibliotecas nativas dinámicas y estáticas.
Información específica de los sistemas AIX
Para el enlace de tiempo de ejecución, las aplicaciones se pueden enlazar mediante la opción del cargador -brtl. Si el enlace de tiempo de ejecución provoca un conflicto de símbolos, la aplicación deberá resolverlo renombrando el símbolo en el lado de la aplicación o desactivando el enlace de tiempo de ejecución.
Enlace dinámico en AIX
cc_r -qmkshrobj [-qarch=ppc | -q64] -Ijava_install_dir/include
-o libnm.a nm.cLa opción -qmkshrobj inhabilita el enlace de tiempo de ejecución. Para obtener más información sobre los archivos de objetos compartidos, el enlace de tiempo de ejecución y el uso de las opciones de línea de mandatos de cc y ld, consulte:- Developing and Porting C and C++ Applications on AIX en http://www.redbooks.ibm.com/abstracts/sg245674.html
- El sitio web del compilador C y C++ en https://www.ibm.com/marketplace/ibm-c-and-c-plus-plus-compiler-family
- La documentación en línea de AIX en https://www.ibm.com/support/knowledgecenter/ssw_aix/welcome
Antes de ejecutar un programa Java que utilice métodos nativos, asegúrese de que LIBPATH contiene la lista de directorios que contienen los objetos compartidos para los métodos nativos. Para obtener más información sobre la creación de objetos compartidos de AIX , consulte Desarrollo de aplicaciones C y C++ en AIX . Vaya a https://www.ibm.com/redbooks y busque "SG245674".
Si establece el atributo setuid o setgid en los programas de código nativo JNI, ese valor cambia la variable de entorno LIBPATH efectiva. Este cambio podría producir un comportamiento inesperado o incorrecto con estos programas. Para obtener más información sobre este uso, consulte Developing and Porting C and C++ Applications on AIX en http://www.redbooks.ibm.com/abstracts/sg245674.html, sección 2.3.3.
Cuando crea un programa C o C++ que utiliza la API de invocación JNI para crear una máquina virtual Java y llama al código Java, utilice la opción -L para realizar las tareas siguientes:
- Añada /usr/lib y /lib a la lista de directorios en los que se buscan objetos compartidos. Todos los programas necesitan objetos compartidos que estén almacenados en estos directorios.
- Añada los directorios Java java_install_dir/jre/lib y java_install_dir/jre/lib/j9vm a la lista de directorios en los que se buscan objetos compartidos. Estos directorios contienen las bibliotecas compartidas de Java. También podrá efectuar un enlace con libjvm.so (mediante la opción -ljvm).
Por ejemplo, este código crea un programa C (invAPITest.c) que utiliza la API de invocación de JNI:
cc_r [-qarch=pwr4 | -q64] -Ijava_install_dir/include
-o invAPITest
-L/usr/lib
-L/lib
-Ljava_install_dir/jre/lib/j9vm
-Ljava_install_dir/jre/lib
-ljvm invAPITest.c
Cuando ejecute un programa C o C++ que utilice la API de invocación JNI para ejecutar clases Java, asegúrese de que la vía de acceso de clases se haya configurado correctamente para permitir que la JVM encuentre los archivos de clase. Si modifica la vía de acceso de clases de arranque Java, incluya los archivos SDK necesarios para ejecutar las aplicaciones.
Para determinar si un programa C o C++ que utiliza la API de invocación JNI se ha creado con la opción -bM:UR, utilice el mandato siguiente:
dump [-X64] -ov <program name>
Se generará una salida similar a la siguiente:
>dump -X64 -ov <program name>
***Object Module Header***
# Sections Symbol Ptr # Symbols Opt Hdr Len Flags
4 0x0001a728 1305 120 0x1002
Flags=( EXEC DYNLOAD DEP_SYSTEM )
Timestamp = "14 Oct 03:26:43 2005"
Magic = 0x1f7 (64-bit XCOFF)
***Optional Header***
Tsize Dsize Bsize Tstart Dstart
0x000127f8 0x00001b80 0x00000470 0x1000001f8 0x1100009f0
SNloader SNentry SNtext SNtoc SNdata
0x0004 0x0002 0x0001 0x0002 0x0002
TXTalign DATAalign TOC vstamp entry
0x0005 0x0003 0x110002158 0x0001 0x110002040
maxSTACK maxDATA SNbss magic modtype
0x00000000 0x00000000 0x0003 0x010b UR
-bM:UR . Por ejemplo:export LDR_CNTRL=USERREGS
Si necesita especificar varias opciones con LDR_CNTRL, separe las opciones con el símbolo @.
export AIXTHREAD_SCOPE=S
Otra opción es preestablecer el atributo de ámbito de la hebra en PTHREAD_SCOPE_SYSTEM utilizando la función AIX pthread_attr_setscope cuando se crea la hebra.
- Objeto compartido
- Un objeto compartido es un archivo de objeto individual que tiene el bit SRE (Shared REusable) establecido en la cabecera XCOFF. El bit SRE indica al enlazador que este archivo está enlazado dinámicamente. Estos archivos suelen tener un nombre con el formato <filename> .o, pero también pueden denominarse lib<name> .a para permitir que el enlazador los busque con la opción -lname; pero estos archivos no son archivos de biblioteca de archivado.
- Biblioteca compartida
- Una biblioteca compartida es una biblioteca de archivado con el formato "ar" donde uno o varios de los miembros de archivado es un objeto compartido. Tenga en cuenta que esta biblioteca también puede contener archivos de objetos no compartidos que están enlazados estáticamente. El nombre de una biblioteca compartida tiene el formato lib<name> .a. Este formulario permite al enlazador buscar bibliotecas con la opción -lname.
Para obtener más información, consulte la documentación deAIX.
Los programas también pueden enlazarse dinámicamente con bibliotecas compartidas y objetos compartidos, por ejemplo con la familia de subrutinas dlopen(). La JVM enlaza de esta manera cuando carga bibliotecas nativas (por ejemplo, System.load(), System.loadLibrary(), Runtime.getRuntime().load(), Runtime.getRuntime().loadLibrary()).
Para obtener información sobre dlopen , consulte subrutina dlopen.
Para obtener información sobre los mecanismos de carga y enlace de AIX , consulte AIX Mecanismos de enlace y carga.
System.loadLibrary("<library>(<member>)")donde <library> es el nombre del archivado de biblioteca compartida y <member> es el nombre de un miembro de archivado. Por ejemplo:System.loadLibrary("libShared.a(libSample.o)")
Enlace estático en AIX
Puede efectuar enlaces a bibliotecas JNI de forma estática, además de poder hacerlo de forma dinámica. Las bibliotecas estáticas pueden combinarse en la imagen de un lanzador personalizado que inicia un proceso de JVM con las API de invocación.
Supongamos que tenemos
dos bibliotecas estáticas: testlibA y testlibB. Si intenta cargar la biblioteca testlibA en el programa Java mediante un comando como System.loadLibrary("testlibA"), la JVM primero busca en la imagen del programa ejecutable de lanzamiento una rutina llamada JNI_OnLoad_testlibA( ). Si encuentra esta rutina, la JVM utiliza esta biblioteca vinculada estáticamente para proporcionar definiciones JNI. Si no se encuentra la rutina, la JVM pasa a cargar la biblioteca testlibA
de forma dinámica (por ejemplo, libtestlibA.so) buscando en las vías de acceso
especificadas por -Djava.library.path (o LIBPATH).
En AIX, además de habilitar el enlace de tiempo de ejecución especificando -brtl, debe compilar con la opción -bexpall especificada. Este proceso garantiza que el lanzador exporte símbolos (como por ejemplo JNI_OnLoad_testlibA()) y también permite que las bibliotecas compartidas cargadas por el programa ejecutable (como por ejemplo el de la JVM) puedan buscar los símbolos. Para que la JVM efectúe un enlace de forma estática debe poder buscar en el programa ejecutable antes de intentar efectuar un enlace dinámico.
$ cc_r -qpic -brtl -bexpall -brtl testlibA.o testlibB.o -o <launcher>donde < launcher> es el nombre de un programa ejecutable que contiene las imágenes de las bibliotecas testlibA y testlibB , además de ser un lanzador Java que inicia una JVM a través de las API de invocación.La rutina de inicialización de la biblioteca JNI_OnLoad_L, para una biblioteca L, debe devolverJNI_VERSION_1_8(0x00010008).
Información específica de los sistemas Linux
Si el enlace de tiempo de ejecución provoca un conflicto de símbolos, la aplicación deberá resolverlo renombrando el símbolo en el lado de la aplicación o desactivando el enlace de tiempo de ejecución.
Enlace dinámico en Linux
Cuando crea un programa C o C++ que utiliza la API de invocación JNI para crear una máquina virtual Java y llama al código Java, utilice la opción -L para realizar las tareas siguientes:
- Añada /usr/lib y /lib a la lista de directorios en los que se buscan objetos compartidos. Todos los programas necesitan objetos compartidos que estén almacenados en estos directorios.
- Añada los directorios Java java_install_dir/jre/lib y java_install_dir/jre/lib/j9vm a la lista de directorios en los que se buscan objetos compartidos. Estos directorios contienen las bibliotecas compartidas de Java. También podrá efectuar un enlace con libjvm.so (mediante la opción -ljvm).
Por ejemplo, este código crea un programa C (invAPITest.c) que utiliza la API de invocación de JNI:
cc [-m32|-m64] -Ijava_install_dir/include
-o invAPITest
-L/usr/lib
-L/lib
-Ljava_install_dir/jre/lib/j9vm
-Ljava_install_dir/jre/lib
-ljvm invAPITest.c
Cuando ejecute un programa C o C++ que utilice la API de invocación JNI para ejecutar clases Java, asegúrese de que la vía de acceso de clases se haya configurado correctamente para permitir que la JVM encuentre los archivos de clase. Si modifica la vía de acceso de clases de arranque Java, incluya los archivos SDK necesarios para ejecutar las aplicaciones.
Para asegurarse de que una biblioteca JNI exporta las funciones que una aplicación Java debe resolver en tiempo de ejecución, puede examinar la biblioteca utilizando la herramienta nm . Por ejemplo, una biblioteca JNI
denominada libjnitest.so que contiene las rutinas JNI
fooImpl y barImpl deberá
exportar los siguientes símbolos:
$ nm libjnitest.so
000537d0 T Java_mypackage_SampleClass_fooImpl
0004f020 T Java_mypackage_SampleClass_barImpl
De forma similar, el mandato objdump -T lista los símbolos exportados en una biblioteca compartida:
000537d0 g DF .text 00000040 Base 0x60
Java_mypackage_SampleClass_fooImpl
0004f020 g DF .text 00000254 Base 0x60
Java_mypackage_SampleClass_barImpl
- Biblioteca compartida
- Una biblioteca compartida (u objeto compartido) en Linux es una biblioteca de enlace dinámico que se puede enlazar durante la compilación (enlace) o durante la ejecución (enlace en tiempo de ejecución). Mientras el enlace de tiempo de enlace en una biblioteca compartida se efectúa mediante la herramienta de edición de enlazador ld, el enlace en tiempo de ejecución utiliza la familia de funciones dlopen(3).
Los programas también pueden enlazarse dinámicamente con bibliotecas compartidas y objetos compartidos, por ejemplo con la familia de subrutinas dlopen(). La JVM enlaza de esta manera cuando carga bibliotecas nativas (por ejemplo, System.load(), System.loadLibrary(), Runtime.getRuntime().load(), Runtime.getRuntime().loadLibrary()).
Para obtener información sobre dlopen(3), consulte la documentación de Linux man y busque dlopen.
Enlace estático en Linux
Puede efectuar enlaces a bibliotecas JNI de forma estática, además de poder hacerlo de forma dinámica. Las bibliotecas estáticas pueden combinarse en la imagen de un lanzador personalizado que inicia un proceso de JVM con las API de invocación.
Supongamos que tenemos
dos bibliotecas estáticas: testlibA y testlibB. Si intenta cargar la biblioteca testlibA en el programa Java mediante un comando como System.loadLibrary("testlibA"), la JVM primero busca en la imagen del programa ejecutable de lanzamiento una rutina llamada JNI_OnLoad_testlibA( ). Si encuentra esta rutina, la JVM utiliza esta biblioteca vinculada estáticamente para proporcionar definiciones JNI. Si no se encuentra la rutina, la JVM pasa a cargar la biblioteca testlibA
de forma dinámica (por ejemplo, libtestlibA.so) buscando en las vías de acceso
especificadas por -Djava.library.path (o LD_LIBRARY_PATH).
En Linux, debe compilar con la opción -rdynamic especificada para garantizar que el lanzador exporte símbolos (como JNI_OnLoad_testlibA( ) y también permita que las bibliotecas compartidas que carga el programa ejecutable (como la de la JVM) busquen los símbolos. Para que la JVM efectúe un enlace de forma estática debe poder buscar en el programa ejecutable antes de intentar efectuar un enlace dinámico. Sin -rdynamic, los símbolos no estáticos se seguirán exportando desde el programa ejecutable, pero no serán visibles para las bibliotecas compartidas cargadas por el programa. El siguiente ejemplo muestra el uso de -rdynamic:
$ cc -rdynamic testlibA.o testlibB.o -o <launcher>
La rutina de inicialización de la biblioteca JNI_OnLoad_L, para una biblioteca L, debe devolverJNI_VERSION_1_8(0x00010008).
Información específica de los sistemas Windows
Si el enlace de tiempo de ejecución provoca un conflicto de símbolos, la aplicación deberá resolverlo renombrando el símbolo en el lado de la aplicación o desactivando el enlace de tiempo de ejecución.
Enlace dinámico en Windows
Cuando crea un programa C o C++ que utiliza la API de invocación JNI para crear una máquina virtual Java y llama al código Java, utilice la opción de enlazador /link /LIBPATH para realizar la tarea siguiente:
- Añada los directorios Java java_install_dir\jre\bin\ y java_install_dir\jre\bin\j9vm a la lista de directorios en los que se buscan objetos compartidos. Estos directorios contienen las bibliotecas compartidas de Java. También podrá efectuar un enlace con jvm.dll (mediante la opción -ljvm).
En Windows, no se necesitan opciones especiales para el compilador de línea de mandatos cl.exe. Generalmente, se utiliza un compilador de Microsoft, por ejemplo, VC + +. Para obtener más información sobre las opciones de compilador, consulte la documentación del compilador que se está utilizando. De forma predeterminada, VC++ selecciona las bibliotecas que se encuentran en la variable de entorno %LIB%. La variable siempre debe apuntar hacia el subdirectorio \lib del SDK de VC++ como una de las vías de acceso de búsqueda para enlazar bibliotecas.
cl.exe /I java_install_dir\jre\include
/FeinvAPITest
invAPITest.c
/link /LIBPATH:java_install_dir\jre\bin\j9vm
/LIBPATH:java_install_dir\jre\bin
Cuando ejecute un programa C o C++ que utilice la API de invocación JNI para ejecutar clases Java, asegúrese de que la vía de acceso de clases se haya configurado correctamente para permitir que la JVM encuentre los archivos de clase. Si modifica la vía de acceso de clases de arranque Java, incluya los archivos SDK necesarios para ejecutar las aplicaciones.
C:\>dumpbin.exe /EXPORTS jnitest.dll
Dump of file jnitest.dll
File Type: DLL
Section contains the following exports for JNITEST.dll
00000000 characteristics
5412A472 time date stamp Fri Sep 12 03:44:50 2014
0.00 version
1 ordinal base
5 number of functions
5 number of names
ordinal hint RVA name
...
1 27 0000CE10 Java_mypackage_SampleClass_fooImpl = Java_mypackage_SampleClass_fooImpl
2 28 000085A0 Java_mypackage_SampleClass_barImpl = Java_mypackage_SampleClass_barImpl
...
Para obtener más información sobre dumpbin.exe y sus opciones, consulte la documentación de MSDN.
- Bibliotecas de enlace dinámico
- En Windows, los métodos JNI se almacenan normalmente en bibliotecas dinámicas denominadas bibliotecas de enlace dinámico (DLL). Las DLL contienen funciones y datos a los que se puede hacer referencia desde otro módulo de carga, por ejemplo desde una biblioteca dinámica o un programa ejecutable. Los métodos nativos se almacenan en DLL y se enlazan en tiempo de compilación, a través del proceso de enlace, o en tiempo de ejecución, cargando dinámicamente los métodos utilizando las funciones LoadLibrary() y LoadLibraryEx() de la API de Windows. Para obtener más información sobre la familia de funciones LoadLibrary(), consulte la documentación MSDN.
Enlaces estáticos en Windows
Puede efectuar enlaces a bibliotecas JNI de forma estática, además de poder hacerlo de forma dinámica. Las bibliotecas estáticas pueden combinarse en la imagen de un lanzador personalizado que inicia un proceso de JVM con las API de invocación.
Supongamos que tenemos
dos bibliotecas estáticas: testlibA y testlibB. Si intenta cargar la biblioteca testlibA en el programa Java mediante un comando como System.loadLibrary("testlibA"), la JVM primero busca en la imagen del programa ejecutable de lanzamiento una rutina llamada JNI_OnLoad_testlibA( ). Si encuentra esta rutina, la JVM utiliza esta biblioteca vinculada estáticamente para proporcionar definiciones JNI. Si no se encuentra la rutina, la JVM pasa a cargar la biblioteca testlibA
de forma dinámica (por ejemplo, testlibA.dll) buscando en las vías de acceso
especificadas por -Djava.library.path (o PATH).
Windows no impone ninguna opción especial que se deba especificar al crear un programa ejecutable de lanzador.
La rutina de inicialización de la biblioteca JNI_OnLoad_L, para una biblioteca L, debe devolverJNI_VERSION_1_8(0x00010008).
Información específica de los sistemas z/OS
Si el enlace de tiempo de ejecución provoca un conflicto de símbolos, la aplicación deberá resolverlo renombrando el símbolo en el lado de la aplicación o desactivando el enlace de tiempo de ejecución.
Enlace dinámico en z/OS
Cuando crea un programa C o C++ que utiliza la API de invocación JNI para crear una máquina virtual Java y llama al código Java, utilice la opción -L para realizar las tareas siguientes:
- Añada /usr/lib y /lib a la lista de directorios en los que se buscan objetos compartidos. Todos los programas necesitan objetos compartidos que estén almacenados en estos directorios.
- Añada los directorios Java java_install_dir/jre/lib y java_install_dir/jre/lib/j9vm a la lista de directorios en los que se buscan objetos compartidos. Estos directorios contienen las bibliotecas compartidas de Java. También podrá efectuar un enlace con libjvm.so (mediante la opción -ljvm).
Por ejemplo, este código crea un iniciador de API de invocación denominadoinvAPITest mediante la compilación del programa C invAPITest.c:
cc [-q32|-q64] -Ijava_install_dir/jre/include
-o invAPITest
-L/usr/lib
-L/lib
-Ljava_install_dir/jre/lib/j9vm
-Ljava_install_dir/jre/lib
-ljvm invAPITest.c
El valor -q32 o -q64 especifica el modelo de datos en el que se crea el programa. Si omite estos valores se utilizará el modelo de datos predeterminado.
Cuando ejecute un programa C o C++ que utilice la API de invocación JNI para ejecutar clases Java, asegúrese de que la vía de acceso de clases se haya configurado correctamente para permitir que la JVM encuentre los archivos de clase. Si modifica la vía de acceso de clases de arranque Java, incluya los archivos SDK necesarios para ejecutar las aplicaciones.
Para asegurarse de que una biblioteca JNI exporta las funciones que una aplicación Java debe resolver en tiempo de ejecución, puede examinar la biblioteca utilizando la herramienta nm . Por ejemplo, una biblioteca JNI denominada libjnitest.so y que contiene las rutinas JNI fooImpl y barImpl deberá exportar los siguientes símbolos:
$nm libjnitest.so
255552 T Java_mypackage_SampleClass_fooImpl
255528 T Java_mypackage_SampleClass_barImpl
Para obtener más información, consulte Valores predeterminados de opción de compilador.
- Bibliotecas de enlace dinámico
- En sistemas IBM Z® , los métodos JNI normalmente se almacenan en bibliotecas dinámicas denominadas bibliotecas de enlace dinámico (DLL). Las DLL contienen funciones y datos a los que se puede hacer referencia desde otro módulo de carga, por ejemplo desde una biblioteca dinámica o un programa ejecutable. Los métodos nativos se almacenan en DLL y se enlazan en tiempo de compilación, a través del proceso de enlace, o en tiempo de ejecución, cargando dinámicamente los métodos utilizando la IBM Z dllload o la API compatible con POSIX dlopen. Para obtener más información sobre las funciones dllload () y dlopen (), consulte Carga de una DLL.
Los programas también pueden enlazarse dinámicamente con bibliotecas compartidas y objetos compartidos, por ejemplo con las familias de subrutinas dlopen() o dllload(). La JVM enlaza de esta manera cuando carga bibliotecas nativas (por ejemplo, System.load(), System.loadLibrary(), Runtime.getRuntime().load(), Runtime.getRuntime().loadLibrary()).
Para obtener información sobre estas subrutinas, consulte dlopen () y dllload ().
Enlace estático en z/OS
Puede efectuar enlaces a bibliotecas JNI de forma estática, además de poder hacerlo de forma dinámica. Las bibliotecas estáticas pueden combinarse en la imagen de un lanzador personalizado que inicia un proceso de JVM con las API de invocación.
Supongamos que tenemos
dos bibliotecas estáticas: testlibA y testlibB. Si intenta cargar la biblioteca testlibA en el programa Java mediante un comando como System.loadLibrary("testlibA"), la JVM primero busca en la imagen del programa ejecutable de lanzamiento una rutina llamada JNI_OnLoad_testlibA( ). Si encuentra esta rutina, la JVM utiliza esta biblioteca vinculada estáticamente para proporcionar definiciones JNI. Si no se encuentra la rutina, la JVM pasa a cargar la biblioteca testlibA
de forma dinámica (por ejemplo, libtestlibA.so) buscando en las vías de acceso
especificadas por -Djava.library.path (o LIBPATH).
Wc,DLL, para asegurarse de que el programa ejecutable se crea como una DLLWc,EXPORTALL, para asegurarse de que los símbolos del programa ejecutable se exportan y quedan disponibles para la búsqueda por parte de las bibliotecas compartidas cargadas por el programa.
cc -c -Wc,DLL,EXPORTALL launcher.c -o launcher.o
cc testlibA.o testlibB.o launcher.o -o launcher
También puede eliminar EXPORTALL, en cuyo caso el programa exporta símbolos específicos mediante #pragma export. Para obtener más información, consulte #pragma export.
La rutina de inicialización de la biblioteca JNI_OnLoad_L, para una biblioteca L, debe devolverJNI_VERSION_1_8(0x00010008).