Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents

Overview

ByteBuffers are not meant to be accessed concurrently. But our NioFilter classes, particularly, NioSslEngine manipulate ByteBuffers, and are themselves subject to concurrent access. As a result it's often necessary to protect ByteBuffers from concurrent access.

Not only must we protect ByteBuffers from concurrent access, we also need to ensure that ByteBuffers are returned to their pool when they are no longer needed.

The purpose of the ByteBuffer sharing framework is to provide this coordination and pool management.

The framework leverages the try-with-resources syntax to deliver exclusive ByteBuffer access in lexical blocks. The ByteBufferSharing class provides a couple open() methods (one of which supports timeout). These methods return an AutoCloseable "resource", suitable for assignment in a try-with-resources variable declaration. The Java language guarantees that close() will be called on such a resource when the lexical block is left (either through normal program flow or exception). The framework leverages that close() call as a signal to release locks and reduce reference counts.

PlantUML
@startuml
interface AutoCloseable {
void close()
}
interface ByteBufferSharing extends AutoCloseable {
ByteBuffer getBuffer()
ByteBuffer expandWriteBufferIfNeeded(int newCapacity)
ByteBuffer expandReadBufferIfNeeded(int newCapacity)
}

class ByteBufferVendor {
ByteBufferVendor(ByteBuffer bufferArg, BufferType bufferType, BufferPool bufferPool)
ByteBufferSharing open()
ByteBufferSharing open(long time, TimeUnit unit)
void destruct()
}

ByteBufferVendor .. ByteBuffer : derived\nassociation
@enduml

more


Internals

PlantUML
@startuml
interface AutoCloseable {
void close()
}
interface ByteBufferSharing extends AutoCloseable {
ByteBuffer getBuffer()
ByteBuffer expandWriteBufferIfNeeded(int newCapacity)
ByteBuffer expandReadBufferIfNeeded(int newCapacity)
}

class ByteBufferVendor {
ByteBufferVendor(ByteBuffer bufferArg, BufferType bufferType, BufferPool bufferPool)
ByteBufferSharing open()
ByteBufferSharing open(long time, TimeUnit unit)
void destruct()
}

interface ByteBufferVendor.ByteBufferSharingInternal extends ByteBufferSharing {
void releaseBuffer()
}
class ByteBufferVendor.ByteBufferSharingInternalImpl implements ByteBufferVendor.ByteBufferSharingInternal {}

ByteBufferVendor "sharing" *-- ByteBufferVendor.ByteBufferSharingInternal
ByteBufferVendor "lock" *-- ReentrantLock
ByteBufferVendor "isDestructed" *-- AtomicBoolean
ByteBufferVendor "counter" *-- AtomicInteger

ByteBufferVendor.ByteBufferSharingInternalImpl "buffer\n0..1" --> "1" ByteBuffer
ByteBufferVendor.ByteBufferSharingInternalImpl "bufferPool\n*" --> "1" BufferPool
ByteBufferVendor.ByteBufferSharingInternalImpl "bufferType\n*" --> "1" BufferType

ByteBufferVendor .. ByteBuffer : derived\nassociation
@enduml

ByteBuffers are not meant to be accessed concurrently. But our NioFilter classes, particularly, NioSslEngine manipulate ByteBuffers, and are themselves subject to concurrent access. As a result it's often necessary to protect ByteBuffers from concurrent access.

Not only must we protect ByteBuffers from concurrent access, we also need to ensure that ByteBuffers are returned to their pool when they are no longer needed.

The purpose of the ByteBuffer sharing framework is to provide this coordination and pool management.

...

The ByteBufferSharingInternalImpl class (a private, static internal class of ByteBufferVendor) is the main implementation of the "resource" class just mentioned. It implements AutoCloseable so it's usable as a resource in try-with-resources. It also implements a public interface, ByteBufferSharing, for use by clients within a try-with-resources block. It's this interface that a user of ByteBuffers will be most interested in:

...