English English

Java 14 - Acceder a la memoria externa que está fuera del montón de Java

Desde Java 9 cada nueva versión de Java tiene módulos incubadores, que contienen características que aún están en desarrollo y que pueden ser probadas por los desarrolladores.
Una de estas incubadoras es la API "Foreign-Memory Access API" (JEP 370) que será presentada en este tutorial.

Se puede acceder a un segmento de memoria a través de una dirección de memoria, que se comprobará de antemano si forma parte del límite de su segmento de memoria de referencia. Si desea acceder a una dirección de memoria no comprobada y ésta formaba parte de un segmento de memoria que el cliente tenía, entonces debe reinterpretar el desplazamiento de la dirección no comprobada con respecto a la dirección base del segmento (operación de rebase: MemoryAddress::rebase). Si un segmento de memoria como ese no existe, entonces puedes usar MemorySegment::ofNativeRestricted de fábrica en su lugar. Esta fábrica sólo se puede utilizar si la propiedad JDK "foreign.restricted" no está establecida en el valor "permit" y debe utilizarse con cuidado.
Sólo un hilo puede acceder (y ser propietario de a) un determinado segmento de memoria a la vez, lo que garantiza la "seguridad temporal".
Otro hilo accede a un segmento de memoria ocupado, después de que el titular (propietario) del segmento de memoria haya cerrado el segmento. Si desea acceder y editar la dirección de memoria en paralelo, puede utilizar un "divisor", que divide un segmento de memoria en rodajas. Cada rebanada es utilizada entonces por ciertos hilos para realizar partes de la tarea completa. El segmento de memoria no puede cerrarse durante este proceso para reforzar la seguridad.


Este API asegura eso:

  • Puede funcionar con varios tipos de memoria extraña (por ejemplo: memoria persistente, memoria gestionada, etc.)
  • No socava la seguridad de la "Java Runtime Machine"
  • Las distribuciones se hacen de forma explícita en su código Java.
  • Énfasis en la usabilidad en comparación con otras alternativas (ejemplo: "ByteBuffer API")

Si quieres compilar tu aplicación con esta API, entonces tienes que añadir el módulo "jdk.incubator.foreign".
Ejemplo (Si utiliza la línea de comandos):

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

 

Un ejemplo de aplicación con la API de Acceso a la Memoria Extranjera

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" crea un "handle" para editar y obtener los valores de un Entero de una cierta ubicación de memoria. "ByteOrder.naOrder()" nos dice que usemos el orden de los bytes de la RAM (memoria) del sistema operativo. Se devuelve un objeto "VarHandle", que también tiene los siguientes métodos "set" para establecer un determinado valor en una dirección de memoria y "get" para obtener un valor de una determinada dirección de memoria.
Se crea un segmento de memoria con la función "MemorySegment.allocateNative", que se llamará en un bloque "try-with-resources" para asegurarse de que el segmento de memoria creado se libera al final del código del programa.
Se puede obtener la dirección de memoria base de un determinado segmento de memoria con el método "baseAddress()".

 

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

Más sobre este nuevo Foreign-Memory Access API:
https://openjdk.java.net/jeps/383

Usamos cookies en nuestro sitio web. Algunas de ellas son esenciales para el funcionamiento del sitio, mientras que otras nos ayudan a mejorar el sitio web y también la experiencia del usuario (cookies de rastreo). Puedes decidir por ti mismo si quieres permitir el uso de las cookies. Ten en cuenta que si las rechazas, puede que no puedas usar todas las funcionalidades del sitio web.