Debug di JNI

Se si pensa di avere un problema JNI, è possibile eseguire dei controlli che consentono di diagnosticare le transizioni JNI.

Gli errori nel codice JNI possono verificarsi in diversi modi:
  • Il programma si blocca durante l'esecuzione di un metodo nativo (il più comune).
  • Il programma si blocca un po' di tempo dopo il ritorno dal metodo nativo, spesso durante la GC (non così comune).
  • Un codice JNI non valido causa dei deadlock poco dopo la restituzione da un metodo nativo (occasionale).

Se si ritiene che si sia verificato un problema con l'interazione tra il codice nativo scritto dall'utente e la JVM (ovvero, un problema JNI), è possibile eseguire controlli che consentono di diagnosticare le transizioni JNI. Per eseguire questi controlli, specificare l'opzione -Xcheck:jni quando si avvia JVM.

L'opzione -Xcheck:jni attiva una serie di funzioni wrapper intorno alle funzioni JNI. Le funzioni wrapper eseguono controlli sui parametri in entrata. Questi controlli includono:
  • Se la chiamata e la chiamata che ha inizializzato JNI si trovano sullo stesso thread.
  • Se i parametri dell'oggetto sono oggetti validi.
  • Se i riferimenti locali o globali fanno riferimento a oggetti validi.
  • Se il tipo di un campo corrisponde alla chiamata Get<Type>Field o Set<Type>Field .
  • Se gli ID campo statici e non statici sono validi.
  • Se le stringhe sono valide e non null.
  • Se gli elementi dell'array non sono null.
  • I tipi sugli elementi dell'array.

L'output da -Xcheck:jni viene visualizzato nel flusso di errore standard e si presenta come:

JVMJNCK059W: JNI warning in FindClass: argument #2 is a malformed identifier ("invalid.name")
JVMJNCK090W: Warning detected in com/ibm/examples/JNIExample.nativeMethod() [Ljava/lang/String];
La prima riga indica:
  • Il livello di errore (errore, avvertenza o avviso).
  • L'API JNI in cui è stato rilevato l'errore.
  • Una spiegazione del problema.
L'ultima riga indica il metodo nativo eseguito quando è stato rilevato l'errore.

È possibile specificare ulteriori opzioni secondarie utilizzando -Xcheck:jni:<suboption>[,<...>]. Le opzioni secondarie utili sono:

all
Verificare l'applicazione e le classi di sistema.
verbose
Tenere traccia di alcune attività e funzioni JNI.
trace
Tenere traccia di tutte le funzioni JNI.
nobounds
Non eseguire il controllo dei limiti su stringhe e array.
nonfatal
Non uscire quando vengono rilevati errori.
nowarn
Non visualizzare avvertenze.
noadvice
Non visualizzare il consiglio.
novalist
Non controllare il riutilizzo di va_list (vedere la nota alla fine di questa sezione).
pedantic
Eseguire verifiche più approfondite, ma più lente.
valist
Controllare il riuso di va_list (vedere la nota alla fine della sezione).
help
Stampare le informazioni di aiuto.

L'opzione -Xcheck:jni potrebbe ridurre le prestazioni in quanto è completa quando convalida i parametri forniti.

Nota:

Su alcune piattaforme, il riutilizzo di un va_list in una seconda chiamata JNI (ad esempio, quando si richiama CallStaticVoidMethod() due volte con lo stesso argomento) causa il danneggiamento di va_list e l'esito negativo della seconda chiamata. Per assicurarsi che va_list non sia danneggiato, utilizzare la macro C va_copy() standard nella prima chiamata. Per impostazione predefinita, -Xcheck:jni garantisce che va_listnon vengano riutilizzati. Utilizzare l'opzione secondaria novalist per disabilitare questo controllo solo se la piattaforma consente il riutilizzo di va_list senza va_copy. Le piattaforme z/OS® consentono il va_list riutilizzo e per impostazione predefinita viene utilizzato -Xcheck:jni:novalist . Per abilitare il controllo del riutilizzo va_list , utilizzare l'opzione -Xcheck:jni:valist .