Path: blob/master/src/java.base/share/classes/java/nio/Buffer.java
41152 views
/*1* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.nio;2627import jdk.internal.access.JavaNioAccess;28import jdk.internal.access.SharedSecrets;29import jdk.internal.access.foreign.MemorySegmentProxy;30import jdk.internal.access.foreign.UnmapperProxy;31import jdk.internal.misc.ScopedMemoryAccess;32import jdk.internal.misc.ScopedMemoryAccess.Scope;33import jdk.internal.misc.Unsafe;34import jdk.internal.misc.VM.BufferPool;35import jdk.internal.vm.annotation.ForceInline;36import jdk.internal.vm.annotation.IntrinsicCandidate;3738import java.io.FileDescriptor;39import java.util.Spliterator;4041/**42* A container for data of a specific primitive type.43*44* <p> A buffer is a linear, finite sequence of elements of a specific45* primitive type. Aside from its content, the essential properties of a46* buffer are its capacity, limit, and position: </p>47*48* <blockquote>49*50* <p> A buffer's <i>capacity</i> is the number of elements it contains. The51* capacity of a buffer is never negative and never changes. </p>52*53* <p> A buffer's <i>limit</i> is the index of the first element that should54* not be read or written. A buffer's limit is never negative and is never55* greater than its capacity. </p>56*57* <p> A buffer's <i>position</i> is the index of the next element to be58* read or written. A buffer's position is never negative and is never59* greater than its limit. </p>60*61* </blockquote>62*63* <p> There is one subclass of this class for each non-boolean primitive type.64*65*66* <h2> Transferring data </h2>67*68* <p> Each subclass of this class defines two categories of <i>get</i> and69* <i>put</i> operations: </p>70*71* <blockquote>72*73* <p> <i>Relative</i> operations read or write one or more elements starting74* at the current position and then increment the position by the number of75* elements transferred. If the requested transfer exceeds the limit then a76* relative <i>get</i> operation throws a {@link BufferUnderflowException}77* and a relative <i>put</i> operation throws a {@link78* BufferOverflowException}; in either case, no data is transferred. </p>79*80* <p> <i>Absolute</i> operations take an explicit element index and do not81* affect the position. Absolute <i>get</i> and <i>put</i> operations throw82* an {@link IndexOutOfBoundsException} if the index argument exceeds the83* limit. </p>84*85* </blockquote>86*87* <p> Data may also, of course, be transferred in to or out of a buffer by the88* I/O operations of an appropriate channel, which are always relative to the89* current position.90*91*92* <h2> Marking and resetting </h2>93*94* <p> A buffer's <i>mark</i> is the index to which its position will be reset95* when the {@link #reset reset} method is invoked. The mark is not always96* defined, but when it is defined it is never negative and is never greater97* than the position. If the mark is defined then it is discarded when the98* position or the limit is adjusted to a value smaller than the mark. If the99* mark is not defined then invoking the {@link #reset reset} method causes an100* {@link InvalidMarkException} to be thrown.101*102*103* <h2> Invariants </h2>104*105* <p> The following invariant holds for the mark, position, limit, and106* capacity values:107*108* <blockquote>109* {@code 0} {@code <=}110* <i>mark</i> {@code <=}111* <i>position</i> {@code <=}112* <i>limit</i> {@code <=}113* <i>capacity</i>114* </blockquote>115*116* <p> A newly-created buffer always has a position of zero and a mark that is117* undefined. The initial limit may be zero, or it may be some other value118* that depends upon the type of the buffer and the manner in which it is119* constructed. Each element of a newly-allocated buffer is initialized120* to zero.121*122*123* <h2> Additional operations </h2>124*125* <p> In addition to methods for accessing the position, limit, and capacity126* values and for marking and resetting, this class also defines the following127* operations upon buffers:128*129* <ul>130*131* <li><p> {@link #clear} makes a buffer ready for a new sequence of132* channel-read or relative <i>put</i> operations: It sets the limit to the133* capacity and the position to zero. </p></li>134*135* <li><p> {@link #flip} makes a buffer ready for a new sequence of136* channel-write or relative <i>get</i> operations: It sets the limit to the137* current position and then sets the position to zero. </p></li>138*139* <li><p> {@link #rewind} makes a buffer ready for re-reading the data that140* it already contains: It leaves the limit unchanged and sets the position141* to zero. </p></li>142*143* <li><p> The {@link #slice} and {@link #slice(int,int) slice(index,length)}144* methods create a subsequence of a buffer: They leave the limit and the145* position unchanged. </p></li>146*147* <li><p> {@link #duplicate} creates a shallow copy of a buffer: It leaves148* the limit and the position unchanged. </p></li>149*150* </ul>151*152*153* <h2> Read-only buffers </h2>154*155* <p> Every buffer is readable, but not every buffer is writable. The156* mutation methods of each buffer class are specified as <i>optional157* operations</i> that will throw a {@link ReadOnlyBufferException} when158* invoked upon a read-only buffer. A read-only buffer does not allow its159* content to be changed, but its mark, position, and limit values are mutable.160* Whether or not a buffer is read-only may be determined by invoking its161* {@link #isReadOnly isReadOnly} method.162*163*164* <h2> Thread safety </h2>165*166* <p> Buffers are not safe for use by multiple concurrent threads. If a167* buffer is to be used by more than one thread then access to the buffer168* should be controlled by appropriate synchronization.169*170*171* <h2> Invocation chaining </h2>172*173* <p> Methods in this class that do not otherwise have a value to return are174* specified to return the buffer upon which they are invoked. This allows175* method invocations to be chained; for example, the sequence of statements176*177* <blockquote><pre>178* b.flip();179* b.position(23);180* b.limit(42);</pre></blockquote>181*182* can be replaced by the single, more compact statement183*184* <blockquote><pre>185* b.flip().position(23).limit(42);</pre></blockquote>186*187*188* @author Mark Reinhold189* @author JSR-51 Expert Group190* @since 1.4191*/192193public abstract class Buffer {194// Cached unsafe-access object195static final Unsafe UNSAFE = Unsafe.getUnsafe();196197static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();198199/**200* The characteristics of Spliterators that traverse and split elements201* maintained in Buffers.202*/203static final int SPLITERATOR_CHARACTERISTICS =204Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED;205206// Invariants: mark <= position <= limit <= capacity207private int mark = -1;208private int position = 0;209private int limit;210private int capacity;211212// Used by heap byte buffers or direct buffers with Unsafe access213// For heap byte buffers this field will be the address relative to the214// array base address and offset into that array. The address might215// not align on a word boundary for slices, nor align at a long word216// (8 byte) boundary for byte[] allocations on 32-bit systems.217// For direct buffers it is the start address of the memory region. The218// address might not align on a word boundary for slices, nor when created219// using JNI, see NewDirectByteBuffer(void*, long).220// Should ideally be declared final221// NOTE: hoisted here for speed in JNI GetDirectBufferAddress222long address;223224// Used by buffers generated by the memory access API (JEP-370)225final MemorySegmentProxy segment;226227228// Creates a new buffer with given address and capacity.229//230Buffer(long addr, int cap, MemorySegmentProxy segment) {231this.address = addr;232this.capacity = cap;233this.segment = segment;234}235236// Creates a new buffer with the given mark, position, limit, and capacity,237// after checking invariants.238//239Buffer(int mark, int pos, int lim, int cap, MemorySegmentProxy segment) { // package-private240if (cap < 0)241throw createCapacityException(cap);242this.capacity = cap;243this.segment = segment;244limit(lim);245position(pos);246if (mark >= 0) {247if (mark > pos)248throw new IllegalArgumentException("mark > position: ("249+ mark + " > " + pos + ")");250this.mark = mark;251}252}253254/**255* Returns an {@code IllegalArgumentException} indicating that the source256* and target are the same {@code Buffer}. Intended for use in257* {@code put(src)} when the parameter is the {@code Buffer} on which the258* method is being invoked.259*260* @return IllegalArgumentException261* With a message indicating equal source and target buffers262*/263static IllegalArgumentException createSameBufferException() {264return new IllegalArgumentException("The source buffer is this buffer");265}266267/**268* Verify that the capacity is nonnegative.269*270* @param capacity271* The new buffer's capacity, in $type$s272*273* @throws IllegalArgumentException274* If the {@code capacity} is a negative integer275*/276static IllegalArgumentException createCapacityException(int capacity) {277assert capacity < 0 : "capacity expected to be negative";278return new IllegalArgumentException("capacity < 0: ("279+ capacity + " < 0)");280}281282/**283* Returns this buffer's capacity.284*285* @return The capacity of this buffer286*/287public final int capacity() {288return capacity;289}290291/**292* Returns this buffer's position.293*294* @return The position of this buffer295*/296public final int position() {297return position;298}299300/**301* Sets this buffer's position. If the mark is defined and larger than the302* new position then it is discarded.303*304* @param newPosition305* The new position value; must be non-negative306* and no larger than the current limit307*308* @return This buffer309*310* @throws IllegalArgumentException311* If the preconditions on {@code newPosition} do not hold312*/313public Buffer position(int newPosition) {314if (newPosition > limit | newPosition < 0)315throw createPositionException(newPosition);316if (mark > newPosition) mark = -1;317position = newPosition;318return this;319}320321/**322* Verify that {@code 0 < newPosition <= limit}323*324* @param newPosition325* The new position value326*327* @throws IllegalArgumentException328* If the specified position is out of bounds.329*/330private IllegalArgumentException createPositionException(int newPosition) {331String msg = null;332333if (newPosition > limit) {334msg = "newPosition > limit: (" + newPosition + " > " + limit + ")";335} else { // assume negative336assert newPosition < 0 : "newPosition expected to be negative";337msg = "newPosition < 0: (" + newPosition + " < 0)";338}339340return new IllegalArgumentException(msg);341}342343/**344* Returns this buffer's limit.345*346* @return The limit of this buffer347*/348public final int limit() {349return limit;350}351352/**353* Sets this buffer's limit. If the position is larger than the new limit354* then it is set to the new limit. If the mark is defined and larger than355* the new limit then it is discarded.356*357* @param newLimit358* The new limit value; must be non-negative359* and no larger than this buffer's capacity360*361* @return This buffer362*363* @throws IllegalArgumentException364* If the preconditions on {@code newLimit} do not hold365*/366public Buffer limit(int newLimit) {367if (newLimit > capacity | newLimit < 0)368throw createLimitException(newLimit);369limit = newLimit;370if (position > newLimit) position = newLimit;371if (mark > newLimit) mark = -1;372return this;373}374375/**376* Verify that {@code 0 < newLimit <= capacity}377*378* @param newLimit379* The new limit value380*381* @throws IllegalArgumentException382* If the specified limit is out of bounds.383*/384private IllegalArgumentException createLimitException(int newLimit) {385String msg = null;386387if (newLimit > capacity) {388msg = "newLimit > capacity: (" + newLimit + " > " + capacity + ")";389} else { // assume negative390assert newLimit < 0 : "newLimit expected to be negative";391msg = "newLimit < 0: (" + newLimit + " < 0)";392}393394return new IllegalArgumentException(msg);395}396397/**398* Sets this buffer's mark at its position.399*400* @return This buffer401*/402public Buffer mark() {403mark = position;404return this;405}406407/**408* Resets this buffer's position to the previously-marked position.409*410* <p> Invoking this method neither changes nor discards the mark's411* value. </p>412*413* @return This buffer414*415* @throws InvalidMarkException416* If the mark has not been set417*/418public Buffer reset() {419int m = mark;420if (m < 0)421throw new InvalidMarkException();422position = m;423return this;424}425426/**427* Clears this buffer. The position is set to zero, the limit is set to428* the capacity, and the mark is discarded.429*430* <p> Invoke this method before using a sequence of channel-read or431* <i>put</i> operations to fill this buffer. For example:432*433* <blockquote><pre>434* buf.clear(); // Prepare buffer for reading435* in.read(buf); // Read data</pre></blockquote>436*437* <p> This method does not actually erase the data in the buffer, but it438* is named as if it did because it will most often be used in situations439* in which that might as well be the case. </p>440*441* @return This buffer442*/443public Buffer clear() {444position = 0;445limit = capacity;446mark = -1;447return this;448}449450/**451* Flips this buffer. The limit is set to the current position and then452* the position is set to zero. If the mark is defined then it is453* discarded.454*455* <p> After a sequence of channel-read or <i>put</i> operations, invoke456* this method to prepare for a sequence of channel-write or relative457* <i>get</i> operations. For example:458*459* <blockquote><pre>460* buf.put(magic); // Prepend header461* in.read(buf); // Read data into rest of buffer462* buf.flip(); // Flip buffer463* out.write(buf); // Write header + data to channel</pre></blockquote>464*465* <p> This method is often used in conjunction with the {@link466* java.nio.ByteBuffer#compact compact} method when transferring data from467* one place to another. </p>468*469* @return This buffer470*/471public Buffer flip() {472limit = position;473position = 0;474mark = -1;475return this;476}477478/**479* Rewinds this buffer. The position is set to zero and the mark is480* discarded.481*482* <p> Invoke this method before a sequence of channel-write or <i>get</i>483* operations, assuming that the limit has already been set484* appropriately. For example:485*486* <blockquote><pre>487* out.write(buf); // Write remaining data488* buf.rewind(); // Rewind buffer489* buf.get(array); // Copy data into array</pre></blockquote>490*491* @return This buffer492*/493public Buffer rewind() {494position = 0;495mark = -1;496return this;497}498499/**500* Returns the number of elements between the current position and the501* limit.502*503* @return The number of elements remaining in this buffer504*/505public final int remaining() {506int rem = limit - position;507return rem > 0 ? rem : 0;508}509510/**511* Tells whether there are any elements between the current position and512* the limit.513*514* @return {@code true} if, and only if, there is at least one element515* remaining in this buffer516*/517public final boolean hasRemaining() {518return position < limit;519}520521/**522* Tells whether or not this buffer is read-only.523*524* @return {@code true} if, and only if, this buffer is read-only525*/526public abstract boolean isReadOnly();527528/**529* Tells whether or not this buffer is backed by an accessible530* array.531*532* <p> If this method returns {@code true} then the {@link #array() array}533* and {@link #arrayOffset() arrayOffset} methods may safely be invoked.534* </p>535*536* @return {@code true} if, and only if, this buffer537* is backed by an array and is not read-only538*539* @since 1.6540*/541public abstract boolean hasArray();542543/**544* Returns the array that backs this545* buffer <i>(optional operation)</i>.546*547* <p> This method is intended to allow array-backed buffers to be548* passed to native code more efficiently. Concrete subclasses549* provide more strongly-typed return values for this method.550*551* <p> Modifications to this buffer's content will cause the returned552* array's content to be modified, and vice versa.553*554* <p> Invoke the {@link #hasArray hasArray} method before invoking this555* method in order to ensure that this buffer has an accessible backing556* array. </p>557*558* @return The array that backs this buffer559*560* @throws ReadOnlyBufferException561* If this buffer is backed by an array but is read-only562*563* @throws UnsupportedOperationException564* If this buffer is not backed by an accessible array565*566* @since 1.6567*/568public abstract Object array();569570/**571* Returns the offset within this buffer's backing array of the first572* element of the buffer <i>(optional operation)</i>.573*574* <p> If this buffer is backed by an array then buffer position <i>p</i>575* corresponds to array index <i>p</i> + {@code arrayOffset()}.576*577* <p> Invoke the {@link #hasArray hasArray} method before invoking this578* method in order to ensure that this buffer has an accessible backing579* array. </p>580*581* @return The offset within this buffer's array582* of the first element of the buffer583*584* @throws ReadOnlyBufferException585* If this buffer is backed by an array but is read-only586*587* @throws UnsupportedOperationException588* If this buffer is not backed by an accessible array589*590* @since 1.6591*/592public abstract int arrayOffset();593594/**595* Tells whether or not this buffer is596* <a href="ByteBuffer.html#direct"><i>direct</i></a>.597*598* @return {@code true} if, and only if, this buffer is direct599*600* @since 1.6601*/602public abstract boolean isDirect();603604/**605* Creates a new buffer whose content is a shared subsequence of606* this buffer's content.607*608* <p> The content of the new buffer will start at this buffer's current609* position. Changes to this buffer's content will be visible in the new610* buffer, and vice versa; the two buffers' position, limit, and mark611* values will be independent.612*613* <p> The new buffer's position will be zero, its capacity and its limit614* will be the number of elements remaining in this buffer, its mark will be615* undefined. The new buffer will be direct if, and only if, this buffer is616* direct, and it will be read-only if, and only if, this buffer is617* read-only. </p>618*619* @return The new buffer620*621* @since 9622*/623public abstract Buffer slice();624625/**626* Creates a new buffer whose content is a shared subsequence of627* this buffer's content.628*629* <p> The content of the new buffer will start at position {@code index}630* in this buffer, and will contain {@code length} elements. Changes to631* this buffer's content will be visible in the new buffer, and vice versa;632* the two buffers' position, limit, and mark values will be independent.633*634* <p> The new buffer's position will be zero, its capacity and its limit635* will be {@code length}, its mark will be undefined. The new buffer will636* be direct if, and only if, this buffer is direct, and it will be637* read-only if, and only if, this buffer is read-only. </p>638*639* @param index640* The position in this buffer at which the content of the new641* buffer will start; must be non-negative and no larger than642* {@link #limit() limit()}643*644* @param length645* The number of elements the new buffer will contain; must be646* non-negative and no larger than {@code limit() - index}647*648* @return The new buffer649*650* @throws IndexOutOfBoundsException651* If {@code index} is negative or greater than {@code limit()},652* {@code length} is negative, or {@code length > limit() - index}653*654* @since 13655*/656public abstract Buffer slice(int index, int length);657658/**659* Creates a new buffer that shares this buffer's content.660*661* <p> The content of the new buffer will be that of this buffer. Changes662* to this buffer's content will be visible in the new buffer, and vice663* versa; the two buffers' position, limit, and mark values will be664* independent.665*666* <p> The new buffer's capacity, limit, position and mark values will be667* identical to those of this buffer. The new buffer will be direct if, and668* only if, this buffer is direct, and it will be read-only if, and only if,669* this buffer is read-only. </p>670*671* @return The new buffer672*673* @since 9674*/675public abstract Buffer duplicate();676677678// -- Package-private methods for bounds checking, etc. --679680/**681*682* @return the base reference, paired with the address683* field, which in combination can be used for unsafe access into a heap684* buffer or direct byte buffer (and views of).685*/686abstract Object base();687688/**689* Checks the current position against the limit, throwing a {@link690* BufferUnderflowException} if it is not smaller than the limit, and then691* increments the position.692*693* @return The current position value, before it is incremented694*/695final int nextGetIndex() { // package-private696int p = position;697if (p >= limit)698throw new BufferUnderflowException();699position = p + 1;700return p;701}702703final int nextGetIndex(int nb) { // package-private704int p = position;705if (limit - p < nb)706throw new BufferUnderflowException();707position = p + nb;708return p;709}710711/**712* Checks the current position against the limit, throwing a {@link713* BufferOverflowException} if it is not smaller than the limit, and then714* increments the position.715*716* @return The current position value, before it is incremented717*/718final int nextPutIndex() { // package-private719int p = position;720if (p >= limit)721throw new BufferOverflowException();722position = p + 1;723return p;724}725726final int nextPutIndex(int nb) { // package-private727int p = position;728if (limit - p < nb)729throw new BufferOverflowException();730position = p + nb;731return p;732}733734/**735* Checks the given index against the limit, throwing an {@link736* IndexOutOfBoundsException} if it is not smaller than the limit737* or is smaller than zero.738*/739@IntrinsicCandidate740final int checkIndex(int i) { // package-private741if ((i < 0) || (i >= limit))742throw new IndexOutOfBoundsException();743return i;744}745746final int checkIndex(int i, int nb) { // package-private747if ((i < 0) || (nb > limit - i))748throw new IndexOutOfBoundsException();749return i;750}751752final int markValue() { // package-private753return mark;754}755756final void discardMark() { // package-private757mark = -1;758}759760@ForceInline761final ScopedMemoryAccess.Scope scope() {762if (segment != null) {763return segment.scope();764} else {765return null;766}767}768769final void checkScope() {770ScopedMemoryAccess.Scope scope = scope();771if (scope != null) {772scope.checkValidState();773}774}775776static {777// setup access to this package in SharedSecrets778SharedSecrets.setJavaNioAccess(779new JavaNioAccess() {780@Override781public BufferPool getDirectBufferPool() {782return Bits.BUFFER_POOL;783}784785@Override786public ByteBuffer newDirectByteBuffer(long addr, int cap, Object obj, MemorySegmentProxy segment) {787return new DirectByteBuffer(addr, cap, obj, segment);788}789790@Override791public ByteBuffer newMappedByteBuffer(UnmapperProxy unmapperProxy, long address, int cap, Object obj, MemorySegmentProxy segment) {792return new DirectByteBuffer(address, cap, obj, unmapperProxy.fileDescriptor(), unmapperProxy.isSync(), segment);793}794795@Override796public ByteBuffer newHeapByteBuffer(byte[] hb, int offset, int capacity, MemorySegmentProxy segment) {797return new HeapByteBuffer(hb, -1, 0, capacity, capacity, offset, segment);798}799800@Override801public Object getBufferBase(ByteBuffer bb) {802return bb.base();803}804805@Override806public long getBufferAddress(ByteBuffer bb) {807return bb.address;808}809810@Override811public UnmapperProxy unmapper(ByteBuffer bb) {812if (bb instanceof MappedByteBuffer) {813return ((MappedByteBuffer)bb).unmapper();814} else {815return null;816}817}818819@Override820public MemorySegmentProxy bufferSegment(Buffer buffer) {821return buffer.segment;822}823824@Override825public Scope.Handle acquireScope(Buffer buffer, boolean async) {826var scope = buffer.scope();827if (scope == null) {828return null;829}830if (async && scope.ownerThread() != null) {831throw new IllegalStateException("Confined scope not supported");832}833return scope.acquire();834}835836@Override837public void force(FileDescriptor fd, long address, boolean isSync, long offset, long size) {838MappedMemoryUtils.force(fd, address, isSync, offset, size);839}840841@Override842public void load(long address, boolean isSync, long size) {843MappedMemoryUtils.load(address, isSync, size);844}845846@Override847public void unload(long address, boolean isSync, long size) {848MappedMemoryUtils.unload(address, isSync, size);849}850851@Override852public boolean isLoaded(long address, boolean isSync, long size) {853return MappedMemoryUtils.isLoaded(address, isSync, size);854}855856@Override857public void reserveMemory(long size, long cap) {858Bits.reserveMemory(size, cap);859}860861@Override862public void unreserveMemory(long size, long cap) {863Bits.unreserveMemory(size, cap);864}865866@Override867public int pageSize() {868return Bits.pageSize();869}870});871}872873}874875876