CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-grpc--grpc-core

Core gRPC library containing transport implementation, channel abstraction, load balancing, name resolution, and other fundamental gRPC functionalities for Java

Pending
Overview
Eval results
Files

buffer-management.mddocs/

Buffer Management

gRPC Core provides memory-efficient buffer abstractions for handling data in gRPC streams. These interfaces allow different transport implementations to optimize memory usage while providing a consistent API for reading and writing data.

Capabilities

Readable Buffer Interface

Interface for reading data from buffers in a streaming fashion.

/**
 * Interface for readable byte buffers
 * Located: io.grpc.internal.ReadableBuffer
 */
interface ReadableBuffer {
    /**
     * Gets the number of readable bytes remaining in this buffer
     * @return Number of bytes that can be read
     */
    int readableBytes();
    
    /**
     * Reads a single byte as an unsigned integer (0-255)
     * @return Unsigned byte value
     * @throws IndexOutOfBoundsException if no bytes are readable
     */
    int readUnsignedByte();
    
    /**
     * Reads bytes into the destination array
     * @param dest Destination byte array
     * @param destOffset Starting offset in destination array
     * @param length Number of bytes to read
     * @throws IndexOutOfBoundsException if not enough bytes are readable
     */
    void readBytes(byte[] dest, int destOffset, int length);
    
    /**
     * Reads bytes into a newly allocated byte array
     * @param length Number of bytes to read
     * @return Byte array containing the read data
     * @throws IndexOutOfBoundsException if not enough bytes are readable
     */
    void readBytes(byte[] dest);
    
    /**
     * Reads bytes into a new readable buffer
     * @param length Number of bytes to read
     * @return New ReadableBuffer containing the read data
     * @throws IndexOutOfBoundsException if not enough bytes are readable
     */
    ReadableBuffer readBytes(int length);
    
    /**
     * Skips the specified number of bytes
     * @param length Number of bytes to skip
     * @throws IndexOutOfBoundsException if not enough bytes are readable
     */
    void skipBytes(int length);
    
    /**
     * Checks if this buffer has a backing byte array
     * @return true if hasArray() and array() are supported
     */
    boolean hasArray();
    
    /**
     * Gets the backing byte array (if available)
     * @return Backing byte array
     * @throws UnsupportedOperationException if hasArray() returns false
     */
    byte[] array();
    
    /**
     * Gets the offset in the backing array where readable data starts
     * @return Array offset
     * @throws UnsupportedOperationException if hasArray() returns false
     */
    int arrayOffset();
    
    /**
     * Closes the buffer and releases any associated resources
     */
    void close();
}

Writable Buffer Interface

Interface for writing data to buffers.

/**
 * Interface for writable byte buffers
 * Located: io.grpc.internal.WritableBuffer
 */
interface WritableBuffer {
    /**
     * Writes bytes from the source array to this buffer
     * @param src Source byte array
     * @param srcOffset Starting offset in source array
     * @param length Number of bytes to write
     * @throws IndexOutOfBoundsException if buffer doesn't have enough space
     */
    void write(byte[] src, int srcOffset, int length);
    
    /**
     * Writes all bytes from the source array to this buffer
     * @param src Source byte array
     * @throws IndexOutOfBoundsException if buffer doesn't have enough space
     */
    void write(byte[] src);
    
    /**
     * Writes a single byte to this buffer
     * @param b Byte value to write
     * @throws IndexOutOfBoundsException if buffer doesn't have enough space
     */
    void write(int b);
    
    /**
     * Gets the number of bytes that can still be written to this buffer
     * @return Number of writable bytes remaining
     */
    int writableBytes();
    
    /**
     * Gets the number of bytes that have been written and can be read
     * @return Number of readable bytes
     */
    int readableBytes();
    
    /**
     * Releases the buffer and returns it as a ReadableBuffer
     * After calling this method, the WritableBuffer should not be used
     * @return ReadableBuffer containing the written data
     */
    ReadableBuffer readableBuffer();
}

Writable Buffer Allocator Interface

Interface for allocating writable buffers.

/**
 * Interface for allocating writable buffers
 * Located: io.grpc.internal.WritableBufferAllocator
 */
interface WritableBufferAllocator {
    /**
     * Allocates a new writable buffer with the specified capacity hint
     * @param capacityHint Hint for the desired buffer capacity
     * @return New WritableBuffer instance
     */
    WritableBuffer allocate(int capacityHint);
}

Buffer Implementations

Composite Readable Buffer

Implementation that combines multiple readable buffers into a single logical buffer.

/**
 * Composite readable buffer implementation
 * Located: io.grpc.internal.CompositeReadableBuffer
 */
class CompositeReadableBuffer implements ReadableBuffer {
    /**
     * Creates a new composite buffer
     */
    public CompositeReadableBuffer();
    
    /**
     * Adds a buffer to the end of this composite buffer
     * @param buffer Buffer to add
     * @throws IllegalArgumentException if buffer is null
     */
    public void addBuffer(ReadableBuffer buffer);
    
    @Override
    public int readableBytes();
    
    @Override
    public int readUnsignedByte();
    
    @Override
    public void readBytes(byte[] dest, int destOffset, int length);
    
    @Override
    public void readBytes(byte[] dest);
    
    @Override
    public ReadableBuffer readBytes(int length);
    
    @Override
    public void skipBytes(int length);
    
    @Override
    public boolean hasArray();
    
    @Override
    public byte[] array();
    
    @Override
    public int arrayOffset();
    
    @Override
    public void close();
}

Array-Based Buffer Implementations

Simple implementations using byte arrays as backing storage.

/**
 * ReadableBuffer implementation backed by a byte array
 * Located: io.grpc.internal.ReadableBuffers
 */
class ReadableBuffers {
    /**
     * Creates a readable buffer wrapping the entire byte array
     * @param bytes Byte array to wrap
     * @return ReadableBuffer wrapping the array
     */
    public static ReadableBuffer wrap(byte[] bytes);
    
    /**
     * Creates a readable buffer wrapping part of a byte array
     * @param bytes Byte array to wrap
     * @param offset Starting offset in the array
     * @param length Number of bytes to include
     * @return ReadableBuffer wrapping the specified array section
     */
    public static ReadableBuffer wrap(byte[] bytes, int offset, int length);
    
    /**
     * Creates an empty readable buffer
     * @return Empty ReadableBuffer
     */
    public static ReadableBuffer empty();
}

/**
 * WritableBuffer implementation backed by a byte array
 * Located: io.grpc.internal.WritableBuffers
 */
class WritableBuffers {
    /**
     * Creates a writable buffer with the specified initial capacity
     * @param capacity Initial capacity in bytes
     * @return WritableBuffer with the specified capacity
     */
    public static WritableBuffer allocate(int capacity);
}

Buffer Usage Patterns

Reading Data from Streams

import io.grpc.internal.ReadableBuffer;
import io.grpc.internal.CompositeReadableBuffer;

// Reading from a single buffer
ReadableBuffer buffer = getMessageBuffer();
byte[] messageData = new byte[buffer.readableBytes()];
buffer.readBytes(messageData);
buffer.close();

// Reading from composite buffer (multiple chunks)
CompositeReadableBuffer composite = new CompositeReadableBuffer();
composite.addBuffer(chunk1);
composite.addBuffer(chunk2);
composite.addBuffer(chunk3);

// Read the entire composite as one logical buffer
byte[] fullMessage = new byte[composite.readableBytes()];
composite.readBytes(fullMessage);
composite.close();

Writing Data to Streams

import io.grpc.internal.WritableBuffer;
import io.grpc.internal.WritableBufferAllocator;

// Allocate buffer for writing
WritableBufferAllocator allocator = getBufferAllocator();
WritableBuffer buffer = allocator.allocate(1024);

// Write data to buffer
byte[] messageData = serializeMessage(message);
buffer.write(messageData);

// Convert to readable buffer for transmission
ReadableBuffer readable = buffer.readableBuffer();
sendBuffer(readable);

Custom Buffer Allocator

import io.grpc.internal.WritableBufferAllocator;
import io.grpc.internal.WritableBuffer;

// Custom allocator implementation
public class PooledBufferAllocator implements WritableBufferAllocator {
    private final BufferPool pool;
    
    public PooledBufferAllocator(BufferPool pool) {
        this.pool = pool;
    }
    
    @Override
    public WritableBuffer allocate(int capacityHint) {
        // Get buffer from pool based on capacity hint
        return pool.borrowBuffer(capacityHint);
    }
}

Memory Management

Buffer Lifecycle

  1. Allocation: Buffers are allocated through allocator interfaces
  2. Writing: Data is written to WritableBuffer instances
  3. Conversion: WritableBuffers are converted to ReadableBuffers
  4. Reading: Data is read from ReadableBuffer instances
  5. Cleanup: Buffers are closed to release resources

Resource Management Best Practices

// Always close buffers to prevent memory leaks
ReadableBuffer buffer = null;
try {
    buffer = receiveBuffer();
    processBuffer(buffer);
} finally {
    if (buffer != null) {
        buffer.close();
    }
}

// Or use try-with-resources if buffer implements AutoCloseable
try (ReadableBuffer buffer = receiveBuffer()) {
    processBuffer(buffer);
}

Performance Considerations

  • Buffer Reuse: Implement buffer pooling for high-throughput scenarios
  • Copy Avoidance: Use hasArray() to access backing arrays directly when possible
  • Composite Buffers: Use for scatter-gather operations to avoid copying
  • Capacity Hints: Provide accurate capacity hints to reduce allocations
  • Early Release: Close buffers as soon as reading is complete

Error Handling

Buffer operations handle errors through:

  • IndexOutOfBoundsException: Thrown when reading beyond buffer capacity
  • IllegalArgumentException: Thrown for invalid parameters (null buffers, negative lengths)
  • UnsupportedOperationException: Thrown when operations are not supported (e.g., array() when hasArray() is false)
  • Resource Cleanup: Buffers implement proper cleanup in close() methods
  • State Validation: Operations check buffer state and throw appropriate exceptions

Install with Tessl CLI

npx tessl i tessl/maven-io-grpc--grpc-core

docs

buffer-management.md

builders-factories.md

core-utilities.md

index.md

load-balancing-name-resolution.md

service-providers.md

transport-layer.md

tile.json