Class JCOBridgeStream<T>
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
TThe .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
-
IEnumerable<T>
- 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
this[int]
Gets or sets the element at the specified index.
public T this[int index] { get; set; }
Parameters
indexintZero-based index of the element to access.
Property Value
- T
The element of type
Tatindex.
Exceptions
- ArgumentOutOfRangeException
indexis 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
Telements 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
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
destinationT[]The target array to copy elements into.
destinationIndexintZero-based index in
destinationat which copying begins. Defaults to0.
Exceptions
- ArgumentNullException
destinationis null.- ArgumentOutOfRangeException
destinationIndexis negative or greater than or equal to the length ofdestination.- ArgumentException
destinationdoes not have enough capacity fromdestinationIndexto 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
disposingbooltrue 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
bufferbyte[]The byte array from which to copy bytes to the current stream.
offsetintThe offset in the buffer at which to begin copying bytes to the current stream.
countintThe 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
countvalue 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
offsetparameter minus the length of thebufferparameter is less than thecountparameter.- ArgumentNullException
The
bufferparameter 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
bufferReadOnlySpan<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
bufferbyte[]The buffer to write data from.
offsetintThe zero-based byte offset in
bufferfrom which to begin copying bytes to the stream.countintThe maximum number of bytes to write.
cancellationTokenCancellationTokenThe 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
bufferReadOnlyMemory<byte>The buffer to write data from.
cancellationTokenCancellationTokenThe 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
valuebyteA 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
valuecauses the stream exceed its maximum capacity.