From 380c1ab2fc73f2a02f46f5cf2bdeb44908a257b6 Mon Sep 17 00:00:00 2001 From: poketopa Date: Mon, 19 Oct 2026 15:33:22 +0900 Subject: [PATCH] fix(core): fall back when the byte array buffer pool is exhausted acquire() returned pool.poll() directly, so once every pooled buffer was in use the Kotlin null check threw "poll(...) must not be null". Keep the pool's buffer size and allocate a fresh buffer of that size instead. --- .../core/codec/ByteArrayBufferPool.kt | 5 ++- .../core/codec/ByteArrayBufferPoolTest.kt | 45 +++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 core/src/test/kotlin/com/kakao/actionbase/core/codec/ByteArrayBufferPoolTest.kt diff --git a/core/src/main/kotlin/com/kakao/actionbase/core/codec/ByteArrayBufferPool.kt b/core/src/main/kotlin/com/kakao/actionbase/core/codec/ByteArrayBufferPool.kt index 969625338..8a63527dc 100644 --- a/core/src/main/kotlin/com/kakao/actionbase/core/codec/ByteArrayBufferPool.kt +++ b/core/src/main/kotlin/com/kakao/actionbase/core/codec/ByteArrayBufferPool.kt @@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory class ByteArrayBufferPool( private val pool: ConcurrentLinkedQueue, + private val bufferSize: Int = Constants.Codec.DEFAULT_BUFFER_SIZE, ) { companion object { private val logger = LoggerFactory.getLogger(ByteArrayBufferPool::class.java) @@ -31,7 +32,7 @@ class ByteArrayBufferPool( pool.add(ByteArrayBuffer(bufferSize)) } - return ByteArrayBufferPool(pool) + return ByteArrayBufferPool(pool, bufferSize) } @JvmStatic @@ -58,7 +59,7 @@ class ByteArrayBufferPool( return value } - fun acquire(): ByteArrayBuffer = pool.poll() + fun acquire(): ByteArrayBuffer = pool.poll() ?: ByteArrayBuffer(bufferSize) fun release(buffer: ByteArrayBuffer) { pool.add(buffer) diff --git a/core/src/test/kotlin/com/kakao/actionbase/core/codec/ByteArrayBufferPoolTest.kt b/core/src/test/kotlin/com/kakao/actionbase/core/codec/ByteArrayBufferPoolTest.kt new file mode 100644 index 000000000..1b06e1c67 --- /dev/null +++ b/core/src/test/kotlin/com/kakao/actionbase/core/codec/ByteArrayBufferPoolTest.kt @@ -0,0 +1,45 @@ +package com.kakao.actionbase.core.codec + +import kotlin.test.assertContentEquals +import kotlin.test.assertEquals +import kotlin.test.assertNotSame + +import org.junit.jupiter.api.Test + +class ByteArrayBufferPoolTest { + companion object { + private const val BUFFER_SIZE = 64 + } + + @Test + fun `use should encode with a new buffer when the pool is exhausted`() { + val pool = ByteArrayBufferPool.create(poolSize = 1, bufferSize = BUFFER_SIZE) + + val outer = + pool.use { pooled -> + pooled.putValue(1) + val inner = + pool.use { allocated -> + assertNotSame(pooled, allocated) + allocated.putValue(2).toByteArray() + } + assertContentEquals(unpooled(2), inner) + pooled.toByteArray() + } + + assertContentEquals(unpooled(1), outer) + } + + @Test + fun `acquire should allocate a buffer of the pool's buffer size when the pool is exhausted`() { + val pool = ByteArrayBufferPool.create(poolSize = 1, bufferSize = BUFFER_SIZE) + val pooled = pool.acquire() + + val allocated = pool.acquire() + + assertNotSame(pooled, allocated) + assertEquals(BUFFER_SIZE, allocated.length) + } + + private fun unpooled(value: Int): ByteArray = ByteArray(BUFFER_SIZE).buffer().putValue(value).toByteArray() +}