Synchronisation

Lorsque vous obtenez des éléments de tableau à l'aide d'un appel Get<Type>ArrayElements, vous devez penser à la synchronisation.

Que les données soient épinglées ou non, deux entités sont impliquées dans l'accès aux données :
  • Code Java™ dans lequel l'entité de données est déclarée et utilisée
  • Le code natif qui accède aux données via JNI

Ces deux entités étant probablement des unités d'exécution distinctes, des conflits se produisent.

Examinez le scénario suivant dans une implémentation JNI de copie :
  1. Un programme Java crée un grand tableau et le remplit partiellement avec des données.
  2. Le programme Java appelle la fonction d'écriture native pour écrire les données sur un socket.
  3. Le natif JNI qui implémente write() appelle GetByteArrayElements.
  4. GetByteArrayElements copie le contenu du tableau dans un tampon et le retourne à l'interface native.
  5. L'unité d'exécution native JNI commence à écrire une région du tampon dans le socket.
  6. Pendant que l'unité d'exécution est occupée à écrire, une autre unité d'exécution (Java ou native) s'exécute et copie davantage de données dans le tableau (en dehors de la région en cours d'écriture).
  7. L'unité d'exécution JNI native termine l'écriture de la région vers le socket.
  8. L'unité d'exécution native JNI appelle ReleaseByteArrayElements avec le mode 0 pour indiquer qu'elle a terminé son opération avec le tableau.
  9. La machine virtuelle, qui voit le mode 0, recopie l'ensemble du contenu du tampon vers le tableau et remplace les données écrites par la seconde unité d'exécution.

Dans ce cas, le code fonctionne avec une JVM qui épingle. Comme chaque unité d'exécution écrit uniquement ses propres données et que l'indicateur de mode est ignoré, aucun conflit ne se produit. Ce scénario est un autre exemple de la manière dont un code qui n'est pas écrit strictement conformément à la spécification fonctionne avec une implémentation de JVM mais pas avec une autre. Bien que ce scénario implique une copie d'éléments de tableau, les données épinglées peuvent être également endommagées lorsque deux unités d'exécution y accèdent simultanément.

Attachez une attention particulière à la manière dont vous synchronisez l'accès aux éléments de tableau. Vous pouvez utiliser les interfaces JNI pour accéder aux régions des tableaux et chaînes Java afin de réduire les problèmes liés à ce type d'interaction. Dans le scénario, l'unité d'exécution qui écrit les données écrit dans sa propre région. L'unité d'exécution qui lit les données, lit uniquement sa propre région. Cette méthode fonctionne avec chaque implémentation JNI.