/*
* Copyright ( c ) 2000 , 2022 , Oracle and / or its affiliates . All rights reserved .
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER .
*
* This code is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 only , as
* published by the Free Software Foundation . Oracle designates this
* particular file as subject to the " Classpath " exception as provided
* by Oracle in the LICENSE file that accompanied this code .
*
* This code is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* version 2 for more details ( a copy is included in the LICENSE file that
* accompanied this code ) .
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work ; if not , write to the Free Software Foundation ,
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* Please contact Oracle , 500 Oracle Parkway , Redwood Shores , CA 94065 USA
* or visit www . oracle . com if you need additional information or have any
* questions .
*/
package java.nio;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.access.foreign.UnmapperProxy;
import jdk.internal.foreign.AbstractMemorySegmentImpl;
import jdk.internal.foreign.MemorySessionImpl;
import jdk.internal.misc.ScopedMemoryAccess;
import jdk.internal.misc.Unsafe;
import jdk.internal.misc.VM.BufferPool;
import jdk.internal.vm.annotation.ForceInline;
import java.io.FileDescriptor;
import java.lang.foreign.MemorySegment;
import java.lang.ref.Reference;
import java.util.Objects;
import java.util.Spliterator;
/**
* A container for data of a specific primitive type .
*
* < p > A buffer is a linear , finite sequence of elements of a specific
* primitive type . Aside from its content , the essential properties of a
* buffer are its capacity , limit , and position : < / p >
*
* < blockquote >
*
* < p > A buffer ' s < i > capacity < / i > is the number of elements it contains . The
* capacity of a buffer is never negative and never changes . < / p >
*
* < p > A buffer ' s < i > limit < / i > is the index of the first element that should
* not be read or written . A buffer ' s limit is never negative and is never
* greater than its capacity . < / p >
*
* < p > A buffer ' s < i > position < / i > is the index of the next element to be
* read or written . A buffer ' s position is never negative and is never
* greater than its limit . < / p >
*
* < / blockquote >
*
* < p > There is one subclass of this class for each non - boolean primitive type .
*
*
* < h2 > Transferring data < / h2 >
*
* < p > Each subclass of this class defines two categories of < i > get < / i > and
* < i > put < / i > operations : < / p >
*
* < blockquote >
*
* < p > < i > Relative < / i > operations read or write one or more elements starting
* at the current position and then increment the position by the number of
* elements transferred . If the requested transfer exceeds the limit then a
* relative < i > get < / i > operation throws a { @ link BufferUnderflowException }
* and a relative < i > put < / i > operation throws a { @ link
* BufferOverflowException } ; in either case , no data is transferred . < / p >
*
* < p > < i > Absolute < / i > operations take an explicit element index and do not
* affect the position . Absolute < i > get < / i > and < i > put < / i > operations throw
* an { @ link IndexOutOfBoundsException } if the index argument exceeds the
* limit . < / p >
*
* < / blockquote >
*
* < p > Data may also , of course , be transferred in to or out of a buffer by the
* I / O operations of an appropriate channel , which are always relative to the
* current position .
*
*
* < h2 > Marking and resetting < / h2 >
*
* < p > A buffer ' s < i > mark < / i > is the index to which its position will be reset
* when the { @ link # reset reset } method is invoked . The mark is not always
* defined , but when it is defined it is never negative and is never greater
* than the position . If the mark is defined then it is discarded when the
* position or the limit is adjusted to a value smaller than the mark . If the
* mark is not defined then invoking the { @ link # reset reset } method causes an
* { @ link InvalidMarkException } to be thrown .
*
*
* < h2 > Invariants < / h2 >
*
* < p > The following invariant holds for the mark , position , limit , and
* capacity values :
*
* < blockquote >
* { @ code 0 } { @ code < = }
* < i > mark < / i > { @ code < = }
* < i > position < / i > { @ code < = }
* < i > limit < / i > { @ code < = }
* < i > capacity < / i >
* < / blockquote >
*
* < p > A newly - created buffer always has a position of zero and a mark that is
* undefined . The initial limit may be zero , or it may be some other value
* that depends upon the type of the buffer and the manner in which it is
* constructed . Each element of a newly - allocated buffer is initialized
* to zero .
*
*
* < h2 > Additional operations < / h2 >
*
* < p > In addition to methods for accessing the position , limit , and capacity
* values and for marking and resetting , this class also defines the following
* operations upon buffers :
*
* < ul >
*
* < li > < p > { @ link # clear } makes a buffer ready for a new sequence of
* channel - read or relative < i > put < / i > operations : It sets the limit to the
* capacity and the position to zero . < / p > < / li >
*
* < li > < p > { @ link # flip } makes a buffer ready for a new sequence of
* channel - write or relative < i > get < / i > operations : It sets the limit to the
* current position and then sets the position to zero . < / p > < / li >
*
* < li > < p > { @ link # rewind } makes a buffer ready for re - reading the data that
* it already contains : It leaves the limit unchanged and sets the position
* to zero . < / p > < / li >
*
* < li > < p > The { @ link # slice } and { @ link # slice ( int , int ) slice ( index , length ) }
* methods create a subsequence of a buffer : They leave the limit and the
* position unchanged . < / p > < / li >
*
* < li > < p > { @ link # duplicate } creates a shallow copy of a buffer : It leaves
* the limit and the position unchanged . < / p > < / li >
*
* < / ul >
*
*
* < h2 > Read - only buffers < / h2 >
*
* < p > Every buffer is readable , but not every buffer is writable . The
* mutation methods of each buffer class are specified as < i > optional
* operations < / i > that will throw a { @ link ReadOnlyBufferException } when
* invoked upon a read - only buffer . A read - only buffer does not allow its
* content to be changed , but its mark , position , and limit values are mutable .
* Whether or not a buffer is read - only may be determined by invoking its
* { @ link # isReadOnly isReadOnly } method .
*
*
* < h2 > Thread safety < / h2 >
*
* < p > Buffers are not safe for use by multiple concurrent threads . If a
* buffer is to be used by more than one thread then access to the buffer
* should be controlled by appropriate synchronization .
*
*
* < h2 > Invocation chaining < / h2 >
*
* < p > Methods in this class that do not otherwise have a value to return are
* specified to return the buffer upon which they are invoked . This allows
* method invocations to be chained ; for example , the sequence of statements
*
* < blockquote > < pre >
* b . flip ( ) ;
* b . position ( 23 ) ;
* b . limit ( 42 ) ; < / pre > < / blockquote >
*
* can be replaced by the single , more compact statement
*
* < blockquote > < pre >
* b . flip ( ) . position ( 23 ) . limit ( 42 ) ; < / pre > < / blockquote >
*
*
* @ author Mark Reinhold
* @ author JSR - 51 Expert Group
* @ since 1 . 4
* @ sealedGraph
*/
public abstract sealed class Buffer
permits ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer,
LongBuffer, ShortBuffer {
// Cached unsafe-access object
static final Unsafe UNSAFE = Unsafe.getUnsafe();
static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
/**
* The characteristics of Spliterators that traverse and split elements
* maintained in Buffers .
*/
static final int SPLITERATOR_CHARACTERISTICS =
Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED;
// Invariants: mark <= position <= limit <= capacity
private int mark = -1 ;
private int position = 0 ;
private int limit;
private int capacity;
// Used by heap byte buffers or direct buffers with Unsafe access
// For heap byte buffers this field will be the address relative to the
// array base address and offset into that array. The address might
// not align on a word boundary for slices, nor align at a long word
// (8 byte) boundary for byte[] allocations on 32-bit systems.
// For direct buffers it is the start address of the memory region. The
// address might not align on a word boundary for slices, nor when created
// using JNI, see NewDirectByteBuffer(void*, long).
// Should ideally be declared final
// NOTE: hoisted here for speed in JNI GetDirectBufferAddress
long address;
// Used by buffers generated by the memory access API (JEP-370)
final MemorySegment segment;
// Creates a new buffer with given address and capacity.
//
Buffer(long addr, int cap, MemorySegment segment) {
this .address = addr;
this .capacity = cap;
this .segment = segment;
}
// Creates a new buffer with the given mark, position, limit, and capacity,
// after checking invariants.
//
Buffer(int mark, int pos, int lim, int cap, MemorySegment segment) { // package-private
if (cap < 0 )
throw createCapacityException(cap);
this .capacity = cap;
this .segment = segment;
limit(lim);
position(pos);
if (mark >= 0 ) {
if (mark > pos)
throw new IllegalArgumentException("mark > position: ("
+ mark + " > " + pos + ")" );
this .mark = mark;
}
}
/**
* Returns an { @ code IllegalArgumentException } indicating that the source
* and target are the same { @ code Buffer } . Intended for use in
* { @ code put ( src ) } when the parameter is the { @ code Buffer } on which the
* method is being invoked .
*
* @ return IllegalArgumentException
* With a message indicating equal source and target buffers
*/
static IllegalArgumentException createSameBufferException() {
return new IllegalArgumentException("The source buffer is this buffer" );
}
/**
* Verify that the capacity is nonnegative .
*
* @ param capacity
* The new buffer ' s capacity , in $ type $ s
*
* @ throws IllegalArgumentException
* If the { @ code capacity } is a negative integer
*/
static IllegalArgumentException createCapacityException(int capacity) {
assert capacity < 0 : "capacity expected to be negative" ;
return new IllegalArgumentException("capacity < 0: ("
+ capacity + " < 0)" );
}
/**
* Returns this buffer ' s capacity .
*
* @ return The capacity of this buffer
*/
public final int capacity() {
return capacity;
}
/**
* Returns this buffer ' s position .
*
* @ return The position of this buffer
*/
public final int position() {
return position;
}
/**
* Sets this buffer ' s position . If the mark is defined and larger than the
* new position then it is discarded .
*
* @ param newPosition
* The new position value ; must be non - negative
* and no larger than the current limit
*
* @ return This buffer
*
* @ throws IllegalArgumentException
* If the preconditions on { @ code newPosition } do not hold
*/
public Buffer position(int newPosition) {
if (newPosition > limit | newPosition < 0 )
throw createPositionException(newPosition);
if (mark > newPosition) mark = -1 ;
position = newPosition;
return this ;
}
/**
* Verify that { @ code 0 < newPosition < = limit }
*
* @ param newPosition
* The new position value
*
* @ throws IllegalArgumentException
* If the specified position is out of bounds .
*/
private IllegalArgumentException createPositionException(int newPosition) {
String msg = null ;
if (newPosition > limit) {
msg = "newPosition > limit: (" + newPosition + " > " + limit + ")" ;
} else { // assume negative
assert newPosition < 0 : "newPosition expected to be negative" ;
msg = "newPosition < 0: (" + newPosition + " < 0)" ;
}
return new IllegalArgumentException(msg);
}
/**
* Returns this buffer ' s limit .
*
* @ return The limit of this buffer
*/
public final int limit() {
return limit;
}
/**
* Sets this buffer ' s limit . If the position is larger than the new limit
* then it is set to the new limit . If the mark is defined and larger than
* the new limit then it is discarded .
*
* @ param newLimit
* The new limit value ; must be non - negative
* and no larger than this buffer ' s capacity
*
* @ return This buffer
*
* @ throws IllegalArgumentException
* If the preconditions on { @ code newLimit } do not hold
*/
public Buffer limit(int newLimit) {
if (newLimit > capacity | newLimit < 0 )
throw createLimitException(newLimit);
limit = newLimit;
if (position > newLimit) position = newLimit;
if (mark > newLimit) mark = -1 ;
return this ;
}
/**
* Verify that { @ code 0 < newLimit < = capacity }
*
* @ param newLimit
* The new limit value
*
* @ throws IllegalArgumentException
* If the specified limit is out of bounds .
*/
private IllegalArgumentException createLimitException(int newLimit) {
String msg = null ;
if (newLimit > capacity) {
msg = "newLimit > capacity: (" + newLimit + " > " + capacity + ")" ;
} else { // assume negative
assert newLimit < 0 : "newLimit expected to be negative" ;
msg = "newLimit < 0: (" + newLimit + " < 0)" ;
}
return new IllegalArgumentException(msg);
}
/**
* Sets this buffer ' s mark at its position .
*
* @ return This buffer
*/
public Buffer mark() {
mark = position;
return this ;
}
/**
* Resets this buffer ' s position to the previously - marked position .
*
* < p > Invoking this method neither changes nor discards the mark ' s
* value . < / p >
*
* @ return This buffer
*
* @ throws InvalidMarkException
* If the mark has not been set
*/
public Buffer reset() {
int m = mark;
if (m < 0 )
throw new InvalidMarkException();
position = m;
return this ;
}
/**
* Clears this buffer . The position is set to zero , the limit is set to
* the capacity , and the mark is discarded .
*
* < p > Invoke this method before using a sequence of channel - read or
* < i > put < / i > operations to fill this buffer . For example :
*
* < blockquote > < pre >
* buf . clear ( ) ; // Prepare buffer for reading
* in . read ( buf ) ; // Read data</pre></blockquote>
*
* < p > This method does not actually erase the data in the buffer , but it
* is named as if it did because it will most often be used in situations
* in which that might as well be the case . < / p >
*
* @ return This buffer
*/
public Buffer clear() {
position = 0 ;
limit = capacity;
mark = -1 ;
return this ;
}
/**
* Flips this buffer . The limit is set to the current position and then
* the position is set to zero . If the mark is defined then it is
* discarded .
*
* < p > After a sequence of channel - read or < i > put < / i > operations , invoke
* this method to prepare for a sequence of channel - write or relative
* < i > get < / i > operations . For example :
*
* < blockquote > < pre >
* buf . put ( magic ) ; // Prepend header
* in . read ( buf ) ; // Read data into rest of buffer
* buf . flip ( ) ; // Flip buffer
* out . write ( buf ) ; // Write header + data to channel</pre></blockquote>
*
* < p > This method is often used in conjunction with the { @ link
* java . nio . ByteBuffer # compact compact } method when transferring data from
* one place to another . < / p >
*
* @ return This buffer
*/
public Buffer flip() {
limit = position;
position = 0 ;
mark = -1 ;
return this ;
}
/**
* Rewinds this buffer . The position is set to zero and the mark is
* discarded .
*
* < p > Invoke this method before a sequence of channel - write or < i > get < / i >
* operations , assuming that the limit has already been set
* appropriately . For example :
*
* < blockquote > < pre >
* out . write ( buf ) ; // Write remaining data
* buf . rewind ( ) ; // Rewind buffer
* buf . get ( array ) ; // Copy data into array</pre></blockquote>
*
* @ return This buffer
*/
public Buffer rewind() {
position = 0 ;
mark = -1 ;
return this ;
}
/**
* Returns the number of elements between the current position and the
* limit .
*
* @ return The number of elements remaining in this buffer
*/
public final int remaining() {
int rem = limit - position;
return rem > 0 ? rem : 0 ;
}
/**
* Tells whether there are any elements between the current position and
* the limit .
*
* @ return { @ code true } if , and only if , there is at least one element
* remaining in this buffer
*/
public final boolean hasRemaining() {
return position < limit;
}
/**
* Tells whether or not this buffer is read - only .
*
* @ return { @ code true } if , and only if , this buffer is read - only
*/
public abstract boolean isReadOnly();
/**
* Tells whether or not this buffer is backed by an accessible
* array .
*
* < p > If this method returns { @ code true } then the { @ link # array ( ) array }
* and { @ link # arrayOffset ( ) arrayOffset } methods may safely be invoked .
* < / p >
*
* @ return { @ code true } if , and only if , this buffer
* is backed by an array and is not read - only
*
* @ since 1 . 6
*/
public abstract boolean hasArray();
/**
* Returns the array that backs this
* buffer & nbsp ; & nbsp ; < i > ( optional operation ) < / i > .
*
* < p > This method is intended to allow array - backed buffers to be
* passed to native code more efficiently . Concrete subclasses
* provide more strongly - typed return values for this method .
*
* < p > Modifications to this buffer ' s content will cause the returned
* array ' s content to be modified , and vice versa .
*
* < p > Invoke the { @ link # hasArray hasArray } method before invoking this
* method in order to ensure that this buffer has an accessible backing
* array . < / p >
*
* @ return The array that backs this buffer
*
* @ throws ReadOnlyBufferException
* If this buffer is backed by an array but is read - only
*
* @ throws UnsupportedOperationException
* If this buffer is not backed by an accessible array
*
* @ since 1 . 6
*/
public abstract Object array();
/**
* Returns the offset within this buffer ' s backing array of the first
* element of the buffer & nbsp ; & nbsp ; < i > ( optional operation ) < / i > .
*
* < p > If this buffer is backed by an array then buffer position < i > p < / i >
* corresponds to array index < i > p < / i > & nbsp ; + & nbsp ; { @ code arrayOffset ( ) } .
*
* < p > Invoke the { @ link # hasArray hasArray } method before invoking this
* method in order to ensure that this buffer has an accessible backing
* array . < / p >
*
* @ return The offset within this buffer ' s array
* of the first element of the buffer
*
* @ throws ReadOnlyBufferException
* If this buffer is backed by an array but is read - only
*
* @ throws UnsupportedOperationException
* If this buffer is not backed by an accessible array
*
* @ since 1 . 6
*/
public abstract int arrayOffset();
/**
* Tells whether or not this buffer is
* < a href = " ByteBuffer . html # direct " > < i > direct < / i > < / a > .
*
* @ return { @ code true } if , and only if , this buffer is direct
*
* @ since 1 . 6
*/
public abstract boolean isDirect();
/**
* Creates a new buffer whose content is a shared subsequence of
* this buffer ' s content .
*
* < p > The content of the new buffer will start at this buffer ' s current
* position . Changes to this buffer ' s content will be visible in the new
* buffer , and vice versa ; the two buffers ' position , limit , and mark
* values will be independent .
*
* < p > The new buffer ' s position will be zero , its capacity and its limit
* will be the number of elements remaining in this buffer , its mark will be
* undefined . The new buffer will be direct if , and only if , this buffer is
* direct , and it will be read - only if , and only if , this buffer is
* read - only . < / p >
*
* @ return The new buffer
*
* @ since 9
*/
public abstract Buffer slice();
/**
* Creates a new buffer whose content is a shared subsequence of
* this buffer ' s content .
*
* < p > The content of the new buffer will start at position { @ code index }
* in this buffer , and will contain { @ code length } elements . Changes to
* this buffer ' s content will be visible in the new buffer , and vice versa ;
* the two buffers ' position , limit , and mark values will be independent .
*
* < p > The new buffer ' s position will be zero , its capacity and its limit
* will be { @ code length } , its mark will be undefined . The new buffer will
* be direct if , and only if , this buffer is direct , and it will be
* read - only if , and only if , this buffer is read - only . < / p >
*
* @ param index
* The position in this buffer at which the content of the new
* buffer will start ; must be non - negative and no larger than
* { @ link # limit ( ) limit ( ) }
*
* @ param length
* The number of elements the new buffer will contain ; must be
* non - negative and no larger than { @ code limit ( ) - index }
*
* @ return The new buffer
*
* @ throws IndexOutOfBoundsException
* If { @ code index } is negative or greater than { @ code limit ( ) } ,
* { @ code length } is negative , or { @ code length > limit ( ) - index }
*
* @ since 13
*/
public abstract Buffer slice(int index, int length);
/**
* Creates a new buffer that shares this buffer ' s content .
*
* < p > The content of the new buffer will be that of this buffer . Changes
* to this buffer ' s content will be visible in the new buffer , and vice
* versa ; the two buffers ' position , limit , and mark values will be
* independent .
*
* < p > The new buffer ' s capacity , limit , position and mark values will be
* identical to those of this buffer . The new buffer will be direct if , and
* only if , this buffer is direct , and it will be read - only if , and only if ,
* this buffer is read - only . < / p >
*
* @ return The new buffer
*
* @ since 9
*/
public abstract Buffer duplicate();
// -- Package-private methods for bounds checking, etc. --
/**
*
* @ return the base reference , paired with the address
* field , which in combination can be used for unsafe access into a heap
* buffer or direct byte buffer ( and views of ) .
*/
abstract Object base();
/**
* Checks the current position against the limit , throwing a { @ link
* BufferUnderflowException } if it is not smaller than the limit , and then
* increments the position .
*
* @ return The current position value , before it is incremented
*/
final int nextGetIndex() { // package-private
int p = position;
if (p >= limit)
throw new BufferUnderflowException();
position = p + 1 ;
return p;
}
final int nextGetIndex(int nb) { // package-private
int p = position;
if (limit - p < nb)
throw new BufferUnderflowException();
position = p + nb;
return p;
}
/**
* Checks the current position against the limit , throwing a { @ link
* BufferOverflowException } if it is not smaller than the limit , and then
* increments the position .
*
* @ return The current position value , before it is incremented
*/
final int nextPutIndex() { // package-private
int p = position;
if (p >= limit)
throw new BufferOverflowException();
position = p + 1 ;
return p;
}
final int nextPutIndex(int nb) { // package-private
int p = position;
if (limit - p < nb)
throw new BufferOverflowException();
position = p + nb;
return p;
}
/**
* Checks the given index against the limit , throwing an { @ link
* IndexOutOfBoundsException } if it is not smaller than the limit
* or is smaller than zero .
*/
final int checkIndex(int i) { // package-private
return Objects.checkIndex(i, limit);
}
final int checkIndex(int i, int nb) { // package-private
if ((i < 0 ) || (nb > limit - i))
throw new IndexOutOfBoundsException();
return i;
}
final int markValue() { // package-private
return mark;
}
final void discardMark() { // package-private
mark = -1 ;
}
@ForceInline
final MemorySessionImpl session() {
if (segment != null ) {
return ((AbstractMemorySegmentImpl)segment).sessionImpl();
} else {
return null ;
}
}
final void checkSession() {
MemorySessionImpl session = session();
if (session != null ) {
session.checkValidState();
}
}
static {
// setup access to this package in SharedSecrets
SharedSecrets.setJavaNioAccess(
new JavaNioAccess() {
@Override
public BufferPool getDirectBufferPool() {
return Bits.BUFFER_POOL;
}
@Override
public ByteBuffer newDirectByteBuffer(long addr, int cap, Object obj, MemorySegment segment) {
return new DirectByteBuffer(addr, cap, obj, segment);
}
@Override
public ByteBuffer newMappedByteBuffer(UnmapperProxy unmapperProxy, long address, int cap, Object obj, MemorySegment segment) {
return new DirectByteBuffer(address, cap, obj, unmapperProxy.fileDescriptor(), unmapperProxy.isSync(), segment);
}
@Override
public ByteBuffer newHeapByteBuffer(byte [] hb, int offset, int capacity, MemorySegment segment) {
return new HeapByteBuffer(hb, -1 , 0 , capacity, capacity, offset, segment);
}
@Override
public Object getBufferBase(Buffer buffer) {
return buffer.base();
}
@Override
public long getBufferAddress(Buffer buffer) {
return buffer.address;
}
@Override
public UnmapperProxy unmapper(Buffer buffer) {
if (buffer instanceof MappedByteBuffer mbb) {
return mbb.unmapper();
} else {
return null ;
}
}
@Override
public MemorySegment bufferSegment(Buffer buffer) {
return buffer.segment;
}
@Override
public void acquireSession(Buffer buffer) {
var scope = buffer.session();
if (scope != null ) {
scope.acquire0();
}
}
@Override
public void releaseSession(Buffer buffer) {
try {
var scope = buffer.session();
if (scope != null ) {
scope.release0();
}
} finally {
Reference.reachabilityFence(buffer);
}
}
@Override
public boolean isThreadConfined(Buffer buffer) {
var scope = buffer.session();
return scope != null && scope.ownerThread() != null ;
}
@Override
public boolean hasSession(Buffer buffer) {
return buffer.session() != null ;
}
@Override
public void force(FileDescriptor fd, long address, boolean isSync, long offset, long size) {
MappedMemoryUtils.force(fd, address, isSync, offset, size);
}
@Override
public void load(long address, boolean isSync, long size) {
MappedMemoryUtils.load(address, isSync, size);
}
@Override
public void unload(long address, boolean isSync, long size) {
MappedMemoryUtils.unload(address, isSync, size);
}
@Override
public boolean isLoaded(long address, boolean isSync, long size) {
return MappedMemoryUtils.isLoaded(address, isSync, size);
}
@Override
public void reserveMemory(long size, long cap) {
Bits.reserveMemory(size, cap);
}
@Override
public void unreserveMemory(long size, long cap) {
Bits.unreserveMemory(size, cap);
}
@Override
public int pageSize() {
return Bits.pageSize();
}
});
}
}
Messung V0.5 in Prozent C=95 H=89 G=91
¤ Dauer der Verarbeitung: 0.31 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland