Versions Compared

Key

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

...

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.

...

In the class diagram at the top of this page you'll see a dotted association between ByteBufferVendor and ByteBuffer labeled "derived association". That's meant to convey the fact that kind of the whole point of the vendor is that it mediates access to a ByteBuffer. In UML terms, there is a derived association between the two, even though you won't see an explicit (direct) object reference in the code.

...

Code Block
languagejava
firstline1
titleYour WRONG Method Returning ByteBufferSharing
ByteBufferSharing WRONG() throws IOException {
  try (final ByteBufferSharing sharing = vendor.open()) {

    // +1 net reference count

    // access ByteBuffer through sharing reference here

    // NEVER DO THIS: you risk the reference count dropping to zero
    // before the caller can bind the reference value in its own
    // try-with-resources block
    return sharing
  }
 
  // +0 net reference count--buffer is potentially eligible
  //    for return to pool before caller can access it!
}

...