Table of Contents

Class JCOBridgeStream<T>

Namespace
MASES.JCOBridge.C2JBridge
Assembly
C2JBridge.dll

An UnmanagedMemoryStream that provides direct .NET stream access to the native memory of a JVM array obtained from ToStream<T>(FileAccess, bool).

public class JCOBridgeStream<T> : UnmanagedMemoryStream, IDisposable, IEnumerable<T>, IEnumerable where T : unmanaged

Type Parameters

T

The .NET primitive type corresponding to the element type of this IJavaArray. Supported types reflect the JVM primitive type system:

JVM type.NET type
booleanbool
bytebyte
shortshort
intint
longlong
floatfloat
doubledouble
charchar

Unsigned types (sbyte, ushort, uint, ulong) are not supported as they have no equivalent in the JVM type system. Passing an unsupported type throws NotSupportedException at runtime; passing a type inconsistent with the actual JVM array element type throws InvalidOperationException.

Inheritance
JCOBridgeStream<T>
Implements
Inherited Members
Extension Methods

Remarks

Instances of this class must be obtained through ToStream<T>(FileAccess, bool); direct instantiation is not supported.

Standard license. The stream operates on a local copy of the JVM array data, consistent with the snapshot already available from ToArray(). There are no constraints on JVM interaction or stream lifetime. When opened with write access, any modifications are written back to the JVM array automatically on Dispose(). If Dispose() is not called explicitly, the finalizer ensures cleanup without adverse effects, though explicit disposal is always preferred.

HPA license — standard access (forceRawMemory = false). The JVM runtime may expose a direct pointer or an internal copy depending on its implementation; in both cases the GC runs freely and JVM interaction is unrestricted. Dispose() should be called promptly to release the JVM resource; relying on the finalizer is discouraged as it keeps the resource held for an indeterminate time.

HPA license — raw memory access (forceRawMemory = true). The JVM garbage collector is suspended for the entire lifetime of this stream. No JVM interaction of any kind is permitted while the stream is alive (no object allocation, no method calls, no blocking operations). Dispose() is mandatory, must be invoked immediately after the memory operation completes, and must not be left to the finalizer. Violating these constraints may result in a deadlock or a JVM crash. Always use a using block.

Performance characteristics. Per-element access through this[int] or IEnumerable<T> on JVM-resident memory is inherently slower than equivalent access on a managed .NET array. The JVM heap and the CLR managed heap occupy separate physical memory regions; each element access risks a TLB miss or CPU cache miss because the hardware prefetcher has no prior knowledge of those pages. A managed array, by contrast, is warm in the CPU cache immediately after any copy and benefits from hardware prefetching and JIT optimisations on subsequent accesses.

This class is therefore most appropriate when the buffer is large enough that copying it into managed memory would be prohibitively expensive in time or space (typically hundreds of MB or more), and the access pattern is sparse or random so that only a small fraction of elements are actually read or written. When the entire buffer must be scanned or compared, prefer AsSpan combined with MemoryExtensions.SequenceEqual{T}(ReadOnlySpan{T}, ReadOnlySpan{T}) or another single-pass SIMD operation, which amortises the cache-miss cost over one contiguous traversal. For repeated access to the same data, a local copy via ArrayPool<T>.Shared.Rent is faster overall.

Properties

Count

Gets the number of elements of type T in the stream.

public int Count { get; }

Property Value

int

this[int]

Gets or sets the element at the specified index.

public T this[int index] { get; set; }

Parameters

index int

Zero-based index of the element to access.

Property Value

T

The element of type T at index.

Exceptions

ArgumentOutOfRangeException

index is negative or greater than or equal to Count.

NotSupportedException

The stream is read-only and a set operation was attempted.

Methods

AsSpan()

Returns a zero-copy ReadOnlySpan<T> over the entire stream contents, starting at offset zero regardless of the current Position.

Prefer this over IEnumerable<T> for bulk comparisons and copies: MemoryExtensions.SequenceEqual{T}(ReadOnlySpan{T}, ReadOnlySpan{T}) dispatches to SIMD hardware intrinsics with no allocations.

public ReadOnlySpan<T> AsSpan()

Returns

ReadOnlySpan<T>

A ReadOnlySpan<T> of length Count backed directly by the native memory buffer.

AsSpanFromPosition()

Returns a zero-copy ReadOnlySpan<T> over the stream contents starting at the current Position.

public ReadOnlySpan<T> AsSpanFromPosition()

Returns

ReadOnlySpan<T>

A ReadOnlySpan<T> whose length equals the number of complete T elements remaining from Position to the end of the stream.

AsWritableSpan()

Returns a zero-copy writable Span<T> over the entire buffer, starting at offset zero regardless of the current position.

Contract: if any element is modified through the returned span, FlushOnDispose() MUST be called before Dispose(bool) to ensure changes are written back. Failing to do so results in silent data loss. For single or sparse writes prefer Write(...), which sets the flush flag automatically.

public Span<T> AsWritableSpan()

Returns

Span<T>

A Span<T> of length Count backed directly by the native memory buffer.

Exceptions

NotSupportedException

Thrown when the buffer exceeds MaxValue elements.

AsWritableSpanFromPosition()

Returns a zero-copy writable Span<T> over the buffer starting at the specified element index.

Contract: if any element is modified through the returned span, FlushOnDispose() MUST be called before Dispose(bool) to ensure changes are written back. Failing to do so results in silent data loss. For single or sparse writes prefer Write(...), which sets the flush flag automatically.

public Span<T> AsWritableSpanFromPosition()

Returns

Span<T>

A Span<T> covering all elements from Position to the end of the stream, backed directly by the native memory buffer.

Exceptions

NotSupportedException

Thrown when the number of remaining elements exceeds MaxValue.

CopyTo(T[], int)

Copies all elements into destination starting at destinationIndex.

On .NET 5+ and .NET Standard 2.1 this operation is backed by ReadOnlySpan<T> and dispatches to SIMD hardware intrinsics with no intermediate allocation. On .NET Framework the copy is performed via MemoryCopy(void*, void*, long, long), which uses the OS-level memcpy implementation and is SIMD-accelerated on all supported platforms without requiring any additional dependency. In both cases no intermediate managed allocation occurs.

public void CopyTo(T[] destination, int destinationIndex = 0)

Parameters

destination T[]

The target array to copy elements into.

destinationIndex int

Zero-based index in destination at which copying begins. Defaults to 0.

Exceptions

ArgumentNullException

destination is null.

ArgumentOutOfRangeException

destinationIndex is negative or greater than or equal to the length of destination.

ArgumentException

destination does not have enough capacity from destinationIndex to hold Count elements.

Dispose(bool)

Releases the unmanaged resources used by the UnmanagedMemoryStream and optionally releases the managed resources.

protected override void Dispose(bool disposing)

Parameters

disposing bool

true to release both managed and unmanaged resources; false to release only unmanaged resources.

~JCOBridgeStream()

Finalizer

protected ~JCOBridgeStream()

FlushOnDispose()

Marks this stream to flush all native memory changes back to the underlying resource on Dispose(bool).

Must be called after any direct write performed through AsWritableSpan() or AsWritableSpanFromPosition() before the stream is closed.

This method is idempotent — calling it multiple times has no additional effect.

public void FlushOnDispose()

GetEnumerator()

Returns an enumerator that iterates through the collection.

public IEnumerator<T> GetEnumerator()

Returns

IEnumerator<T>

An enumerator that can be used to iterate through the collection.

Write(byte[], int, int)

Writes a block of bytes to the current stream using data from a buffer.

public override void Write(byte[] buffer, int offset, int count)

Parameters

buffer byte[]

The byte array from which to copy bytes to the current stream.

offset int

The offset in the buffer at which to begin copying bytes to the current stream.

count int

The number of bytes to write to the current stream.

Exceptions

ObjectDisposedException

The stream is closed.

NotSupportedException

The underlying memory does not support writing. - or -An attempt is made to write to the stream and the CanWrite property is false.- or -The count value is greater than the capacity of the stream.- or -The position is at the end of the stream capacity.

IOException

An I/O error occurs.

ArgumentOutOfRangeException

One of the specified parameters is less than zero.

ArgumentException

The offset parameter minus the length of the buffer parameter is less than the count parameter.

ArgumentNullException

The buffer parameter is null.

Write(ReadOnlySpan<byte>)

Writes a block of bytes to the current unmanaged memory stream using data from the provided span of bytes.

public override void Write(ReadOnlySpan<byte> buffer)

Parameters

buffer ReadOnlySpan<byte>

WriteAsync(byte[], int, int, CancellationToken)

Asynchronously writes a sequence of bytes to the current stream, advances the current position within this stream by the number of bytes written, and monitors cancellation requests.Available starting in .NET Framework 4.6

public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)

Parameters

buffer byte[]

The buffer to write data from.

offset int

The zero-based byte offset in buffer from which to begin copying bytes to the stream.

count int

The maximum number of bytes to write.

cancellationToken CancellationToken

The token to monitor for cancellation requests. The default value is None.

Returns

Task

A task that represents the asynchronous write operation.

WriteAsync(ReadOnlyMemory<byte>, CancellationToken)

Asynchronously writes a span of bytes to the current stream, advances the current position within this stream by the number of bytes written, and monitors cancellation requests.

public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)

Parameters

buffer ReadOnlyMemory<byte>

The buffer to write data from.

cancellationToken CancellationToken

The token to monitor for cancellation requests. The default value is None.

Returns

ValueTask

A task that represents the asynchronous write operation.

WriteByte(byte)

Writes a byte to the current position in the file stream.

public override void WriteByte(byte value)

Parameters

value byte

A byte value written to the stream.

Exceptions

ObjectDisposedException

The stream is closed.

NotSupportedException

The underlying memory does not support writing.- or -An attempt is made to write to the stream and the CanWrite property is false.- or - The current position is at the end of the capacity of the stream.

IOException

The supplied value causes the stream exceed its maximum capacity.