English English

Warning: count(): Parameter must be an array or an object that implements Countable in /var/www/ard-site/templates/ardsite/library/Designer/Content/SingleArticle.php on line 198

Java 14 - Accéder à la mémoire étrangère qui se trouve en dehors du tas de Java

Depuis Java 9, chaque nouvelle version de Java comporte des modules incubateurs, qui contiennent des fonctionnalités encore en cours de développement et qui peuvent être testées par les développeurs.
L'un de ces incubateurs est l'"Foreign-Memory Access API" (JEP 370) qui sera présenté dans ce tutoriel.

Un segment de mémoire est accessible par une adresse mémoire, qui sera vérifiée au préalable si elle fait partie de la limite de votre segment de mémoire référencé. Si vous voulez accéder à une adresse mémoire non vérifiée et qu'elle faisait partie d'un segment de mémoire que le client possédait, vous devez alors réinterpréter le décalage de l'adresse non vérifiée par rapport à l'adresse de base du segment (opération de rebasage : MemoryAddress::rebase). Si un tel segment de mémoire n'existe pas, vous pouvez alors utiliser MemorySegment::ofNativeRestricted factory à la place. Cette factory ne peut être utilisée que si la propriété JDK "foreign.restricted" n'est pas réglée sur la valeur "permit" et doit être utilisée avec précaution.
Un seul thread peut accéder (et être propriétaire) d'un certain segment de mémoire à la fois, ce qui assure une "sécurité temporelle".
Un autre thread a accès à un segment de mémoire occupé, après que le détenteur (propriétaire) du segment de mémoire ait fermé le segment. Si vous voulez accéder et modifier l'adresse de mémoire en parallèle, vous pouvez utiliser un "spliterator", qui divise un segment de mémoire en tranches. Chaque tranche est ensuite utilisée par certains threads pour effectuer des parties de la tâche complète. Le segment de mémoire ne peut pas être fermé pendant ce processus pour des raisons de sécurité.


Cette API garantit cela:

  • Il peut fonctionner sur différents types de mémoire étrangère (exemple : mémoire persistante, mémoire de tas gérée, etc.)
  • Elle ne porte pas atteinte à la sécurité de la "Java Runtime Machine"
  • Les attributions se font de manière explicite dans votre code Java
  • L'accent est mis sur la convivialité par rapport à d'autres solutions (exemple : "ByteBuffer API")

Si vous voulez compiler votre application avec cette API, vous devez alors ajouter le module "jdk.incubator.foreign".
Exemple (si vous utilisez la ligne de commande) :

javac --add-modules jdk.incubator.foreign ForeignMemoryAccess.java

 

Un exemple d'application avec l'API d'accès aux mémoires étrangères

package java14ForeignMemoryAccess;

import java.lang.invoke.VarHandle;
import java.nio.ByteOrder;

import jdk.incubator.foreign.MemoryAddress;
import jdk.incubator.foreign.MemoryHandles;
import jdk.incubator.foreign.MemorySegment;

public class ForeignMemoryAccess {

	public static void main(String[] args) {

		int allocatedBlockSize = 2048;
		int newValue = 1000;
		VarHandle intMemoryHandle = MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder());

		try (MemorySegment accessedSegment = MemorySegment.allocateNative(allocatedBlockSize)) {
			MemoryAddress addressBase = accessedSegment.baseAddress();
			System.out.println("Base Address: " + addressBase);
			System.out.println("Old value of accessed memory: " + intMemoryHandle.get(addressBase));
			System.out.println("Set new value " + newValue + " into the accessed memory.");
			intMemoryHandle.set(addressBase, newValue);
			System.out.println("New value of accessed memory: " + intMemoryHandle.get(addressBase));
		}
	}

}

"MemoryHandles.varHandle" crée une poignée pour éditer et obtenir les valeurs d'un entier d'un certain emplacement de mémoire. "ByteOrder.nativeOrder()" nous indique d'utiliser l'ordre des octets de la RAM (mémoire) du système d'exploitation. Un objet "VarHandle" est renvoyé, qui possède également les méthodes suivantes "set" pour définir une certaine valeur à une adresse mémoire et "get" pour obtenir une valeur à partir d'une certaine adresse mémoire.
Un segment de mémoire est créé avec la fonction "MemorySegment.allocateNative", qui sera appelée dans un bloc "try-with-resources" pour s'assurer que le segment de mémoire créé est libéré à la fin du code du programme.
Vous pouvez obtenir l'adresse mémoire de base d'un certain segment de mémoire avec la méthode "baseAddress()".

 

Documentation:
https://download.java.net/java/GA/jdk14/docs/api/jdk.incubator.foreign/jdk/incubator/foreign/package-summary.html

En savoir plus sur cette nouvelle "Foreign-Memory Access API":
https://openjdk.java.net/jeps/383

We use cookies on our website. Some of them are essential for the operation of the site, while others help us to improve this site and the user experience (tracking cookies). You can decide for yourself whether you want to allow cookies or not. Please note that if you reject them, you may not be able to use all the functionalities of the site.

Ok