Liaison d'exécution JNI
L'interface JNI (Java™ Native Interface) permet la liaison d'exécution à des bibliothèques natives dynamiques et statiques.
Informations spécifiques aux systèmes AIX
Pour les liens d'exécution, les applications peuvent être liées à l'aide de l'option du programme de chargement -brtl. Si la liaison à l'exécution génère un conflit de symboles, vous devez soit le résoudre en renommant le symbole côté application, soit désactiver la liaison à l'exécution.
Liaison dynamique dans AIX
cc_r -qmkshrobj [-qarch=ppc | -q64] -Ijava_install_dir/include
-o libnm.a nm.cL'option -qmkshrobj désactive la liaison d'exécution. Pour plus d'informations sur les fichiers d'objets partagés, la liaison d'exécution et l'utilisation des options de ligne de commande cc et ld, voir :- Développement et portage d'applications C et C++ sous AIX à l'adresse http://www.redbooks.ibm.com/abstracts/sg245674.html
- Le site Web du compilateur C et C++ à l'adresse https://www.ibm.com/marketplace/ibm-c-and-c-plus-plus-compiler-family
- La documentation en ligne d' AIX à l'adresse https://www.ibm.com/support/knowledgecenter/ssw_aix/welcome
Avant d'exécuter un programme Java qui utilise des méthodes natives, vérifiez que LIBPATH contient la liste des répertoires qui contiennent les objets partagés pour les méthodes natives. Pour plus d'informations sur la génération d'objets partagés AIX , voir C and C++ Application Development on AIX . Accédez à https://www.ibm.com/redbooks et recherchez "SG245674".
Si vous définissez l'attribut setuid ou setgid sur les programmes de code natif JNI, ce paramètre change la variable d'environnement LIBPATH effective. Cette modification peut provoquer un comportement inattendu ou incorrect de ces programmes. Pour plus d'informations sur cette utilisation, voir Developing and Porting C and C++ Applications on AIX à l'adresse http://www.redbooks.ibm.com/abstracts/sg245674.html, section 2.3.3.
Lorsque vous générez un programme C ou C++ qui utilise l'API JNI Invocation pour créer une machine virtuelle Java et appelle du code Java, utilisez l'option -L pour effectuer les tâches suivantes:
- Ajoutez /usr/lib et /lib à la liste des répertoires qui sont recherchés pour les objets partagés. Tous les programmes nécessitent les objets partagés stockés dans ces répertoires.
- Ajoutez vos répertoires Java java_install_dir/jre/lib et java_install_dir/jre/lib/j9vm à la liste des répertoires dans lesquels sont recherchés les objets partagés. Ces répertoires contiennent les bibliothèques partagées Java. Vous devez également lier votre programme à libjvm.so (en utilisant l'option -ljvm).
Par exemple, ce code génère un programme C (invAPITest.c) qui utilise l'API d'appel 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
Lorsque vous exécutez un programme C ou C++ qui utilise l'API JNI Invocation pour exécuter des classes Java, vérifiez que le chemin d'accès aux classes est configuré correctement pour permettre à la machine virtuelle Java de trouver vos fichiers de classe. Si vous modifiez le chemin d'accès aux classes d'amorçage Java, incluez les fichiers SDK nécessaires à l'exécution de vos applications.
Pour déterminer si un programme C ou C++ utilisant l'API d'appel JNI a été créé avec l'option -bM:UR, utilisez la commande suivante :
dump [-X64] -ov <program name>
Une sortie similaire à la suivante sera générée :
>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 . Par exemple :export LDR_CNTRL=USERREGS
Si vous devez spécifier plusieurs options avec LDR_CNTRL, séparez ces options avec le symbole @.
export AIXTHREAD_SCOPE=S
Une autre option consiste à prédéfinir l'attribut de portée de l'unité d'exécution sur PTHREAD_SCOPE_SYSTEM à l'aide de la fonction AIX pthread_attr_setscope lors de la création de l'unité d'exécution.
- Objet partagé
- Un objet partagé est un fichier objet unique dont le bit SRE (Shared REusable) est défini dans l'en-tête XCOFF. Le bit SRE indique à l'éditeur de liens que ce fichier est lié dynamiquement. Ces fichiers ont généralement le format de nom <filename>.o, mais ils peuvent également être nommés lib<name> .a pour permettre à l'éditeur de liens de rechercher ces fichiers avec l'option -lname , mais il ne s'agit pas de fichiers de bibliothèque d'archivage.
- Bibliothèque partagée
- Une bibliothèque partagée est un bibliothèque archive de format "ar" dans laquelle un ou plusieurs des membres d'archive est un objet partagé. Cette bibliothèque peut aussi contenir des fichiers objet non partagés qui sont liés statiquement. Une bibliothèque partagée porte un nom de la forme lib<name> .a. Ce formulaire permet à l'éditeur de liens de rechercher des bibliothèques avec l'option -lname.
Pour plus d'informations, voir la documentationAIX.
Les programmes peuvent également se lier dynamiquement à des bibliothèques partagées et des objets partagés, par exemple, en utilisant la famille de sous-routines dlopen(). La JVM se lie de cette façon lorsqu'elle charge des bibliothèques natives (par exemple System.load(), System.loadLibrary(), Runtime.getRuntime().load(), Runtime.getRuntime().loadLibrary()).
Pour plus d'informations sur dlopen , voir dlopen Subroutine.
Pour plus d'informations sur les mécanismes de chargement et de liaison AIX , voir AIX Mécanismes de liaison et de chargement.
System.loadLibrary("<library>(<member>)")Où <library> est le nom de l'archive de bibliothèque partagée et <member> est le nom d'un membre d'archivage. Par exemple :System.loadLibrary("libShared.a(libSample.o)")
Liaison statique dans AIX
Vous pouvez lier statiquement le programme à des bibliothèques JNI, en plus de le lier dynamiquement. Les bibliothèques statiques peuvent être combinées dans l'image d'un lanceur personnalisé qui lance un processus de JVM en utilisant les API Invocation.
Supposez les deux bibliothèques statiques testlibA et testlibB. Si vous tentez de charger la bibliothèque testlibA dans le programme Java en utilisant une commande telle que System.loadLibrary("testlibA"), la JVM recherche d'abord dans l'image du programme exécutable de lancement une routine nommée JNI_OnLoad_testlibA( ). Si cette routine est trouvée, la JVM utilise cette bibliothèque liée statiquement pour fournir des définitions JNI. Si la routine n'est pas trouvée, la JVM charge dynamiquement la bibliothèque testlibA
(par exemple, libtestlibA.so) en
examinant les chemins spécifiés par -Djava.library.path (ou
LIBPATH).
Sous AIX, en plus d'activer la liaison d'exécution en spécifiant -brtl, vous devez générer avec l'option -bexpall spécifiée. Ce processus garantit que le lanceur exporte les symboles (tels que JNI_OnLoad_testlibA()) et permet également que les bibliothèques partagées chargées par le programme exécutable (tel que celui de la JVM) puissent rechercher les symboles. Pour que la JVM se lie statiquement, elle doit pouvoir regarder dans le programme exécutable avant toute tentative de liaison dynamique.
$ cc_r -qpic -brtl -bexpall -brtl testlibA.o testlibB.o -o <launcher>où < launcher> est le nom d'un programme exécutable qui contient les images des bibliothèques testlibA et testlibB , ainsi que le nom d'un lanceur Java qui lance une machine virtuelle Java via les API d'appel.La routine d'initialisation de la bibliothèque JNI_OnLoad_L, pour une bibliothèque L, doit renvoyerJNI_VERSION_1_8(0x00010008).
Informations spécifiques aux systèmes Linux
Si la liaison à l'exécution génère un conflit de symboles, vous devez soit le résoudre en renommant le symbole côté application, soit désactiver la liaison à l'exécution.
Liaison dynamique dans Linux
Lorsque vous générez un programme C ou C++ qui utilise l'API JNI Invocation pour créer une machine virtuelle Java et appelle du code Java, utilisez l'option -L pour effectuer les tâches suivantes:
- Ajoutez /usr/lib et /lib à la liste des répertoires qui sont recherchés pour les objets partagés. Tous les programmes nécessitent les objets partagés stockés dans ces répertoires.
- Ajoutez vos répertoires Java java_install_dir/jre/lib et java_install_dir/jre/lib/j9vm à la liste des répertoires dans lesquels sont recherchés les objets partagés. Ces répertoires contiennent les bibliothèques partagées Java. Vous devez également lier votre programme à libjvm.so (en utilisant l'option -ljvm).
Par exemple, ce code génère un programme C (invAPITest.c) qui utilise l'API d'appel 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
Lorsque vous exécutez un programme C ou C++ qui utilise l'API JNI Invocation pour exécuter des classes Java, vérifiez que le chemin d'accès aux classes est configuré correctement pour permettre à la machine virtuelle Java de trouver vos fichiers de classe. Si vous modifiez le chemin d'accès aux classes d'amorçage Java, incluez les fichiers SDK nécessaires à l'exécution de vos applications.
Pour vous assurer qu'une bibliothèque JNI exporte les fonctions qu'une application Java doit résoudre lors de l'exécution, vous pouvez examiner la bibliothèque à l'aide de l'outil nm . Par exemple, la bibliothèque JNI libjnitest.so qui contient les routines JNI fooImpl et barImpl doit exporter les symboles suivants :
$ nm libjnitest.so
000537d0 T Java_mypackage_SampleClass_fooImpl
0004f020 T Java_mypackage_SampleClass_barImpl
De même, la commande objdump -T liste les symboles exportés dans une bibliothèque partagée :
000537d0 g DF .text 00000040 Base 0x60
Java_mypackage_SampleClass_fooImpl
0004f020 g DF .text 00000254 Base 0x60
Java_mypackage_SampleClass_barImpl
- Bibliothèque partagée
- Une bibliothèque partagée (ou un objet partagé) sous Linux est une bibliothèque de liaison dynamique qui peut être liée au moment de la génération (liaison au moment de la liaison) ou au moment de l'exécution (liaison au moment de l'exécution). La liaison link-time linking par rapport à une bibliothèque partagée est effectuée en utilisant l'éditeur de liaison ld, mais la liaison runtime linking utilise la famille de fonctions dlopen(3).
Les programmes peuvent également se lier dynamiquement à des bibliothèques partagées et des objets partagés, par exemple, en utilisant la famille de sous-routines dlopen(). La JVM se lie de cette façon lorsqu'elle charge des bibliothèques natives (par exemple System.load(), System.loadLibrary(), Runtime.getRuntime().load(), Runtime.getRuntime().loadLibrary()).
Pour plus d'informations sur dlopen(3), consultez la documentation de l'utilisateur Linux et recherchez dlopen.
Liaison statique dans Linux
Vous pouvez lier statiquement le programme à des bibliothèques JNI, en plus de le lier dynamiquement. Les bibliothèques statiques peuvent être combinées dans l'image d'un lanceur personnalisé qui lance un processus de JVM en utilisant les API Invocation.
Supposez les deux bibliothèques statiques testlibA et testlibB. Si vous tentez de charger la bibliothèque testlibA dans le programme Java en utilisant une commande telle que System.loadLibrary("testlibA"), la JVM recherche d'abord dans l'image du programme exécutable de lancement une routine nommée JNI_OnLoad_testlibA( ). Si cette routine est trouvée, la JVM utilise cette bibliothèque liée statiquement pour fournir des définitions JNI. Si la routine n'est pas trouvée, la JVM charge dynamiquement la bibliothèque testlibA
(par exemple, libtestlibA.so) en
examinant les chemins spécifiés par -Djava.library.path (ou
LD_LIBRARY_PATH).
Sur Linux, vous devez construire avec l'option -rdynamic spécifiée pour vous assurer que le lanceur exporte les symboles (tels que JNI_OnLoad_testlibA( ) et permet également aux bibliothèques partagées qui sont chargées par le programme exécutable (comme celle de la JVM) de rechercher les symboles. Pour que la JVM se lie statiquement, elle doit pouvoir regarder dans le programme exécutable avant toute tentative de liaison dynamique. Sans -rdynamic, les symboles non statiques sont toujours exportés depuis le programme exécutable, mais ils ne sont pas visibles par les bibliothèques partagées chargées par le programme. L'exemple suivant montre l'utilisation de -rdynamic:
$ cc -rdynamic testlibA.o testlibB.o -o <launcher>
La routine d'initialisation de la bibliothèque JNI_OnLoad_L, pour une bibliothèque L, doit renvoyerJNI_VERSION_1_8(0x00010008).
Informations spécifiques aux systèmes Windows
Si la liaison à l'exécution génère un conflit de symboles, vous devez soit le résoudre en renommant le symbole côté application, soit désactiver la liaison à l'exécution.
Liaison dynamique dans Windows
Lorsque vous générez un programme C ou C++ qui utilise l'API JNI Invocation pour créer une machine virtuelle Java et appelle du code Java, utilisez l'option d'éditeur de liens /link /LIBPATH pour effectuer la tâche suivante:
- Ajoutez vos répertoires Java java_install_dir\jre\bin\ et java_install_dir\jre\bin\j9vm à la liste des répertoires dans lesquels sont recherchés les objets partagés. Ces répertoires contiennent les bibliothèques partagées Java. Vous devez également lier votre programme à jvm.dll (en utilisant l'option -ljvm).
Sous Windows, aucune option spéciale n'est requise pour le compilateur de ligne de commande cl.exe. En règle générale, un compilateur Microsoft est utilisé, par exemple VC + +. Pour plus d'informations sur les options de compilation, voir la documentation du compilateur utilisé. Par défaut, VC++ sélectionne les bibliothèques présentes dans la variable d'environnement %LIB%. Cette variable doit toujours désigner le sous-répertoire \lib du SDK VC++ parmi les chemins de recherche des bibliothèques de liaison.
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
Lorsque vous exécutez un programme C ou C++ qui utilise l'API JNI Invocation pour exécuter des classes Java, vérifiez que le chemin d'accès aux classes est configuré correctement pour permettre à la machine virtuelle Java de trouver vos fichiers de classe. Si vous modifiez le chemin d'accès aux classes d'amorçage Java, incluez les fichiers SDK nécessaires à l'exécution de vos applications.
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
...
Pour plus d'informations sur dumpbin.exe et ses options, voir la documentation MSDN.
- Bibliothèques de liaison dynamique
- Sous Windows, les méthodes JNI sont généralement stockées dans des bibliothèques dynamiques appelées DLL (Dynamic Link Libraries). Les DLL contiennent des fonctions, et parfois des données, qui peuvent être référencées en dehors de la bibliothèque, par exemple, depuis une bibliothèque dynamique ou un programme exécutable. Les méthodes natives sont stockées dans des DLL et sont liées lors de la génération, via le processus de liaison, ou lors de l'exécution, en chargeant dynamiquement les méthodes à l'aide des fonctions LoadLibrary() et LoadLibraryEx() de l'API Windows. Pour plus d'informations sur la famille de fonctions LoadLibrary(), référez-vous à la documentation MSDN.
Liaison statique dans Windows
Vous pouvez lier statiquement le programme à des bibliothèques JNI, en plus de le lier dynamiquement. Les bibliothèques statiques peuvent être combinées dans l'image d'un lanceur personnalisé qui lance un processus de JVM en utilisant les API Invocation.
Supposez les deux bibliothèques statiques testlibA et testlibB. Si vous tentez de charger la bibliothèque testlibA dans le programme Java en utilisant une commande telle que System.loadLibrary("testlibA"), la JVM recherche d'abord dans l'image du programme exécutable de lancement une routine nommée JNI_OnLoad_testlibA( ). Si cette routine est trouvée, la JVM utilise cette bibliothèque liée statiquement pour fournir des définitions JNI. Si la routine n'est pas trouvée, la JVM charge dynamiquement la bibliothèque testlibA
(par exemple, testlibA.dll) en
examinant les chemins spécifiés par -Djava.library.path (ou
PATH).
Windows n'impose pas d'options spéciales à spécifier lors de la génération d'un programme exécutable de lanceur.
La routine d'initialisation de la bibliothèque JNI_OnLoad_L, pour une bibliothèque L, doit renvoyerJNI_VERSION_1_8(0x00010008).
Informations spécifiques aux systèmes z/OS
Si la liaison à l'exécution génère un conflit de symboles, vous devez soit le résoudre en renommant le symbole côté application, soit désactiver la liaison à l'exécution.
Liaison dynamique dans z/OS
Lorsque vous générez un programme C ou C++ qui utilise l'API JNI Invocation pour créer une machine virtuelle Java et appelle du code Java, utilisez l'option -L pour effectuer les tâches suivantes:
- Ajoutez /usr/lib et /lib à la liste des répertoires qui sont recherchés pour les objets partagés. Tous les programmes nécessitent les objets partagés stockés dans ces répertoires.
- Ajoutez vos répertoires Java java_install_dir/jre/lib et java_install_dir/jre/lib/j9vm à la liste des répertoires dans lesquels sont recherchés les objets partagés. Ces répertoires contiennent les bibliothèques partagées Java. Vous devez également lier votre programme à libjvm.so (en utilisant l'option -ljvm).
Par exemple, ce code génère un programme de lancement d'API d'appel nommé invAPITest en compilant le programme 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
La valeur -q32 ou -q64 indique le modèle de données dans lequel le programme est généré. Si vous omettez ces valeurs, le modèle de données par défaut est utilisé.
Lorsque vous exécutez un programme C ou C++ qui utilise l'API JNI Invocation pour exécuter des classes Java, vérifiez que le chemin d'accès aux classes est configuré correctement pour permettre à la machine virtuelle Java de trouver vos fichiers de classe. Si vous modifiez le chemin d'accès aux classes d'amorçage Java, incluez les fichiers SDK nécessaires à l'exécution de vos applications.
Pour vous assurer qu'une bibliothèque JNI exporte les fonctions qu'une application Java doit résoudre lors de l'exécution, vous pouvez examiner la bibliothèque à l'aide de l'outil nm . Par exemple, la bibliothèque JNI libjnitest.so qui contient les routines JNI fooImpl et barImpl doit exporter les symboles suivants :
$nm libjnitest.so
255552 T Java_mypackage_SampleClass_fooImpl
255528 T Java_mypackage_SampleClass_barImpl
Pour plus d'informations, voir Valeurs par défaut des options de compilation.
- Bibliothèques de liaison dynamique
- Sur les systèmes IBM Z® , les méthodes JNI sont généralement stockées dans des bibliothèques dynamiques appelées DLL (Dynamic Link Libraries). Les DLL contiennent des fonctions, et parfois des données, qui peuvent être référencées en dehors de la bibliothèque, par exemple, depuis une bibliothèque dynamique ou un programme exécutable. Les méthodes natives sont stockées dans des DLL et sont liées lors de la génération, via le processus de liaison, ou lors de l'exécution, en chargeant dynamiquement les méthodes à l'aide de l' IBM Z dllload ou de l' POSIX dlopen. Pour plus d'informations sur les fonctions dllload () et dlopen (), voir Chargement d'une DLL.
Les programmes peuvent également se lier dynamiquement à des bibliothèques partagées et des objets partagés, par exemple, en utilisant les familles de sous-routines dlopen() ou dllload(). La JVM se lie de cette façon lorsqu'elle charge des bibliothèques natives (par exemple System.load(), System.loadLibrary(), Runtime.getRuntime().load(), Runtime.getRuntime().loadLibrary()).
Pour plus d'informations sur ces sous-routines, voir dlopen () et dllload ().
Liaison statique dans z/OS
Vous pouvez lier statiquement le programme à des bibliothèques JNI, en plus de le lier dynamiquement. Les bibliothèques statiques peuvent être combinées dans l'image d'un lanceur personnalisé qui lance un processus de JVM en utilisant les API Invocation.
Supposez les deux bibliothèques statiques testlibA et testlibB. Si vous tentez de charger la bibliothèque testlibA dans le programme Java en utilisant une commande telle que System.loadLibrary("testlibA"), la JVM recherche d'abord dans l'image du programme exécutable de lancement une routine nommée JNI_OnLoad_testlibA( ). Si cette routine est trouvée, la JVM utilise cette bibliothèque liée statiquement pour fournir des définitions JNI. Si la routine n'est pas trouvée, la JVM charge dynamiquement la bibliothèque testlibA
(par exemple, libtestlibA.so) en
examinant les chemins spécifiés par -Djava.library.path (ou
LIBPATH).
Wc,DLL, pour vous assurer que le programme exécutable est généré en tant que DLLWc,EXPORTALL, pour s'assurer que les symboles du programme exécutable sont exportés et mis à disposition pour la recherche par les bibliothèques partagées que le programme charge
cc -c -Wc,DLL,EXPORTALL launcher.c -o launcher.o
cc testlibA.o testlibB.o launcher.o -o launcher
Vous pouvez également supprimer EXPORTALL. Dans ce cas le programme exporte des symboles spécifiques à l'aide de #pragma export. Pour plus d'informations, voir #pragma export.
La routine d'initialisation de la bibliothèque JNI_OnLoad_L, pour une bibliothèque L, doit renvoyerJNI_VERSION_1_8(0x00010008).