Class S3BorrowedBuffer
- java.lang.Object
-
- software.amazon.awssdk.crt.s3.S3BorrowedBuffer
-
- All Implemented Interfaces:
AutoCloseable
public final class S3BorrowedBuffer extends Object implements AutoCloseable
One chunk of an S3 response body, read directly from the client's direct buffer pool memory (seeS3DirectBufferPoolOptions) with no copy. Delivered to handlers that implementS3BorrowedBufferDelivery. The chunk starts at the callback'sobjectRangeStart; its length isasByteBuffer().remaining().Exception: for a GetObject that sets a part number, the native client reads the body into its own temporary memory rather than the pool. Its data is then copied once into a separate buffer that this object owns; that buffer works the same way but is not pool memory, so it does not count toward the pool's ceiling or the JVM direct memory limit.
Lifetime. The buffer holds its memory until
close(), so you can keep it after the callback returns, pass it to another thread, or hold it past client shutdown. Every buffer MUST be closed, on every path including exceptions: until it is closed its memory can't be reused, and once the pool runs out, every request on the client waits.This is not flow control. Holding a buffer open does not slow the download. To pause one, enable
read backpressure, return 0 (or a small increment) fromonResponseBodyBorrowed, and callS3MetaRequest.incrementReadWindow(long)when ready for more. The pause applies at part boundaries: the client stops requesting new parts, and parts already requested arrive whole rather than trimmed to the window, so delivery can exceed it by up to one part.Keep a reference while you read. A buffer that is no longer referenced can be recovered by garbage collection, which frees the memory under the
ByteBufferthatasByteBuffer()returned, so hold theS3BorrowedBufferitself for as long as you use that view. SeeasByteBuffer()for what happens to the view after close.close()can be called any number of times.toByteArray()copies the data to a heapbyte[]and closes the buffer; it works once and later calls throw. Both are safe to call from any thread.asByteBuffer()returns one shared view; useByteBuffer.duplicate()if it may be read from more than one place or thread.A buffer that is never closed is recovered only when it is garbage-collected, after an unbounded delay, and is reported as a leak. The
aws.crt.s3.leakdetectionsystem property controls the report:simple(default): logs warnings, and captures the allocation stack trace for 1 in 128 buffers.paranoid: captures a stack trace for every buffer. Useful for tracking down a leak, but costs more.disabled: no warnings.
Examples
Reading the data during the callback. The buffer is closed before the callback returns, so nothing from it (the buffer or its
ByteBufferview) may be kept and used afterwards.public int onResponseBodyBorrowed(S3BorrowedBuffer buffer, long objectRangeStart, long objectRangeEnd) { try (S3BorrowedBuffer b = buffer) { // closes the buffer when the block exits, even on an exception ByteBuffer data = b.asByteBuffer(); // Read the chunk from data here, for example by writing it to a // channel or updating a checksum. } // Grows the read window by this chunk's length, so the download keeps // going when read backpressure is enabled (ignored otherwise). return (int) (objectRangeEnd - objectRangeStart); }Keeping the buffer after the callback. Hand it to whatever reads it later, and have that code close it. If the hand-off fails, the callback still owns the buffer and must close it.
public int onResponseBodyBorrowed(S3BorrowedBuffer buffer, long objectRangeStart, long objectRangeEnd) { try { // The task now owns the buffer and closes it when done. executor.execute(() -> { try (S3BorrowedBuffer b = buffer) { // closes the buffer when the block exits, even on an exception ByteBuffer data = b.asByteBuffer(); // Read the chunk from data here. } }); } catch (RuntimeException e) { buffer.close(); // not handed off, so close it here throw e; } // Grows the read window now, before the task has read the data. With // read backpressure, return 0 instead and call // S3MetaRequest.incrementReadWindow from the task once it is done. return (int) (objectRangeEnd - objectRangeStart); }
-
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description ByteBufferasByteBuffer()Returns aByteBufferview over the underlying pool memory.voidclose()Releases the pool memory so the client can reuse it for further parts of this or other requests.byte[]toByteArray()Copies the buffer contents into a new heapbyte[](safe to hold indefinitely) and closes this borrowed buffer, returning its pool memory so the client can reuse it for further parts of this or other requests.
-
-
-
Method Detail
-
asByteBuffer
public ByteBuffer asByteBuffer()
Returns aByteBufferview over the underlying pool memory. The returned buffer is a shared reference. Do not mutate its position or limit if other threads may be reading concurrently. UseByteBuffer.duplicate()orByteBuffer.slice()for a private view.The returned buffer is a DIRECT buffer over pool memory, not a heap buffer: it has no backing array (
ByteBuffer.hasArray()isfalse, andByteBuffer.array()throwsUnsupportedOperationException). Read it through theByteBufferAPI (get, bulkget(byte[]), channel writes). If you need abyte[], or bytes that outlive this buffer, usetoByteArray()instead.The memory under this view, and under any duplicate or slice of it, is valid only while this
S3BorrowedBufferis open and still referenced. Once it is closed (or recovered by garbage collection), the memory may be reused for other data: reading the view then returns unrelated bytes rather than failing, and writing to it corrupts another download or upload.- Returns:
- a direct
ByteBuffersliced to the response body length - Throws:
IllegalStateException- if this borrowed buffer has been closed
-
toByteArray
public byte[] toByteArray()
Copies the buffer contents into a new heapbyte[](safe to hold indefinitely) and closes this borrowed buffer, returning its pool memory so the client can reuse it for further parts of this or other requests. SubsequentasByteBuffer()ortoByteArray()calls throw.- Returns:
- a heap byte[] copy of the buffer contents
- Throws:
IllegalStateException- if this borrowed buffer has been closed
-
close
public void close()
Releases the pool memory so the client can reuse it for further parts of this or other requests. Idempotent, safe to call multiple times from any thread. The first call performs the release; subsequent calls are no-ops.After
close()returns, theByteBufferpreviously returned fromasByteBuffer()MUST NOT be read. The underlying pool memory may be reused by another request.- Specified by:
closein interfaceAutoCloseable
-
-