Module jdk.incubator.foreign
Package jdk.incubator.foreign

# Interface MemoryAddress

All Superinterfaces:
  `Addressable`

public sealed interface MemoryAddress extends Addressable
A memory address models a reference into a memory location. Memory addresses are typically obtained using the `MemorySegment.address()` method, and can refer to either off-heap or on-heap memory. Off-heap memory addresses are referred to as native memory addresses (see `isNative()`). Native memory addresses allow clients to obtain a raw memory address (expressed as a long value) which can then be used e.g. when interacting with native code.

Given an address, it is possible to compute its offset relative to a given segment, which can be useful when performing memory dereference operations using a memory access var handle (see `MemoryHandles`).

A memory address is associated with a resource scope; the resource scope determines the lifecycle of the memory address, and whether the address can be used from multiple threads. Memory addresses obtained from numeric values, or from native code, are associated with the global resource scope. Memory addresses obtained from segments are associated with the same scope as the segment from which they have been obtained.

All implementations of this interface must be value-based; programmers should treat instances that are equal as interchangeable and should not use instances for synchronization, or unpredictable behavior may occur. For example, in a future release, synchronization may fail. The `equals` method should be used for comparisons.

Non-platform classes should not implement MemoryAddress directly.

Unless otherwise specified, passing a `null` argument, or an array argument containing one or more `null` elements to a method in this class causes a `NullPointerException` to be thrown.

Implementation Requirements:
  Implementations of this interface are immutable, thread-safe and value-based.

## Field Summary

Fields
Modifier and Type
Field
Description
`static final MemoryAddress`
`NULL`
The native memory address instance modelling the `NULL` address, associated with the global resource scope.

## Method Summary

Modifier and Type
Method
Description
`MemoryAddress`
`addOffset(long offset)`
Creates a new memory address with given offset (in bytes), which might be negative, from current one.
`default MemoryAddress`
`address()`
Map this object into a `MemoryAddress` instance.
`MemorySegment`
`asSegment(long bytesSize, Runnable cleanupAction, ResourceScope scope)`
Returns a new native memory segment with given size and resource scope (replacing the scope already associated with this address), and whose base address is this address.
`MemorySegment`
`asSegment(long bytesSize, ResourceScope scope)`
Returns a new native memory segment with given size and resource scope (replacing the scope already associated with this address), and whose base address is this address.
`boolean`
`equals(Object that)`
Compares the specified object with this address for equality.
`int`
`hashCode()`
Returns the hash code value for this address.
`boolean`
`isNative()`
Is this an off-heap memory address?
`static MemoryAddress`
`ofLong(long value)`
Obtain a native memory address instance from given long address.
`ResourceScope`
`scope()`
Returns the resource scope associated with this memory address.
`long`
`segmentOffset(MemorySegment segment)`
Returns the offset of this memory address into the given segment.
`long`
`toRawLongValue()`
Returns the raw long value associated with this native memory address.

## Field Details

### NULL

static final MemoryAddress NULL
The native memory address instance modelling the `NULL` address, associated with the global resource scope.

## Method Details

### address

default MemoryAddress address()
Description copied from interface: `Addressable`
Map this object into a `MemoryAddress` instance.

Specified by:
  `address` in interface `Addressable`
Returns:
  the `MemoryAddress` instance associated with this object.

### addOffset

MemoryAddress addOffset(long offset)
Creates a new memory address with given offset (in bytes), which might be negative, from current one.

Parameters:
  `offset` - specified offset (in bytes), relative to this address, which should be used to create the new address.
Returns:
  a new memory address with given offset from current one.

### scope

ResourceScope scope()
Returns the resource scope associated with this memory address.

Returns:
  the resource scope associated with this memory address.

### segmentOffset

long segmentOffset(MemorySegment segment)
Returns the offset of this memory address into the given segment. More specifically, if both the segment's base address and this address are native addresses, the result is computed as `this.toRawLongValue() - segment.address().toRawLongValue()`. Otherwise, if both addresses in the form `(B, O1)`, `(B, O2)`, where `B` is the same base heap object and `O1`, `O2` are byte offsets (relative to the base object) associated with this address and the segment's base address, the result is computed as `O1 - O2`.

If the segment's base address and this address are both heap addresses, but with different base objects, the result is undefined and an exception is thrown. Similarly, if the segment's base address is an heap address (resp. off-heap) and this address is an off-heap (resp. heap) address, the result is undefined and an exception is thrown. Otherwise, the result is a byte offset `SO`. If this address falls within the spatial bounds of the given segment, then `0 <= SO < segment.byteSize()`; otherwise, `SO < 0 || SO > segment.byteSize()`.

Parameters:
  `segment` - the segment relative to which this address offset should be computed
Returns:
  the offset of this memory address into the given segment.
Throws:
  `IllegalArgumentException` - if `segment` is not compatible with this address; this can happen, for instance, when `segment` models an heap memory region, while this address is a native address.

### asSegment

MemorySegment asSegment(long bytesSize, ResourceScope scope)
Returns a new native memory segment with given size and resource scope (replacing the scope already associated with this address), and whose base address is this address. This method can be useful when interacting with custom native memory sources (e.g. custom allocators), where an address to some underlying memory region is typically obtained from native code (often as a plain `long` value). The returned segment is not read-only (see `MemorySegment.isReadOnly()`), and is associated with the provided resource scope.

Clients should ensure that the address and bounds refers to a valid region of memory that is accessible for reading and, if appropriate, writing; an attempt to access an invalid memory location from Java code will either return an arbitrary value, have no visible effect, or cause an unspecified exception to be thrown.

This method is equivalent to the following code:

        asSegment(byteSize, null, scope);

This method is restricted. Restricted methods are unsafe, and, if used incorrectly, their use might crash the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on restricted methods, and use safe and supported functionalities, where possible.

Parameters:
  `bytesSize` - the desired size.
  `scope` - the native segment scope.
Returns:
  a new native memory segment with given base address, size and scope.
Throws:
  `IllegalArgumentException` - if `bytesSize <= 0`.
  `IllegalStateException` - if either the scope associated with this address or the provided scope have been already closed, or if access occurs from a thread other than the thread owning either scopes.
  `UnsupportedOperationException` - if this address is not a native address.
  `IllegalCallerException` - if access to this method occurs from a module `M` and the command line option `--enable-native-access` is either absent, or does not mention the module name `M`, or `ALL-UNNAMED` in case `M` is an unnamed module.

### asSegment

MemorySegment asSegment(long bytesSize, Runnable cleanupAction, ResourceScope scope)
Returns a new native memory segment with given size and resource scope (replacing the scope already associated with this address), and whose base address is this address. This method can be useful when interacting with custom native memory sources (e.g. custom allocators), where an address to some underlying memory region is typically obtained from native code (often as a plain `long` value). The returned segment is associated with the provided resource scope.

Clients should ensure that the address and bounds refers to a valid region of memory that is accessible for reading and, if appropriate, writing; an attempt to access an invalid memory location from Java code will either return an arbitrary value, have no visible effect, or cause an unspecified exception to be thrown.

Calling `ResourceScope.close()` on the scope associated with the returned segment will result in calling the provided cleanup action (if any).

This method is restricted. Restricted methods are unsafe, and, if used incorrectly, their use might crash the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on restricted methods, and use safe and supported functionalities, where possible.

Parameters:
  `bytesSize` - the desired size.
  `cleanupAction` - the cleanup action; can be `null`.
  `scope` - the native segment scope.
Returns:
  a new native memory segment with given base address, size and scope.
Throws:
  `IllegalArgumentException` - if `bytesSize <= 0`.
  `IllegalStateException` - if either the scope associated with this address or the provided scope have been already closed, or if access occurs from a thread other than the thread owning either scopes.
  `UnsupportedOperationException` - if this address is not a native address.
  `IllegalCallerException` - if access to this method occurs from a module `M` and the command line option `--enable-native-access` is either absent, or does not mention the module name `M`, or `ALL-UNNAMED` in case `M` is an unnamed module.

### isNative

boolean isNative()
Is this an off-heap memory address?

Returns:
  true, if this is an off-heap memory address.

### toRawLongValue

long toRawLongValue()
Returns the raw long value associated with this native memory address.

Returns:
  The raw long value associated with this native memory address.
Throws:
  `UnsupportedOperationException` - if this memory address is not a native address.
  `IllegalStateException` - if the scope associated with this segment has been already closed, or if access occurs from a thread other than the thread owning either segment.

### equals

boolean equals(Object that)
Compares the specified object with this address for equality. Returns `true` if and only if the specified object is also an address, and it refers to the same memory location as this address.

Overrides:
  `equals` in class `Object`
API Note:
  two addresses might be considered equal despite their associated resource scopes differ. This can happen, for instance, if the same memory address is used to create memory segments with different scopes (using `asSegment(long, ResourceScope)`), and the base address of the resulting segments is then compared.
Parameters:
  `that` - the object to be compared for equality with this address.
Returns:
  `true` if the specified object is equal to this address.
See Also:
  - `Object.hashCode()`
  - `HashMap`

### hashCode

int hashCode()
Returns the hash code value for this address.

Overrides:
  `hashCode` in class `Object`
Returns:
  the hash code value for this address.
See Also:
  - `Object.equals(java.lang.Object)`
  - `System.identityHashCode(java.lang.Object)`

### ofLong

static MemoryAddress ofLong(long value)
Obtain a native memory address instance from given long address. The returned address is associated with the global resource scope.

Parameters:
  `value` - the long address.
Returns:
  the new memory address instance.