How MemorySafeLBQ Prevents OOM in Java Thread Pools: A Deep Dive

This article examines the MemoryLimitedLBQ and MemorySafeLBQ implementations, explains how they use memory‑limiting techniques to avoid Out‑Of‑Memory errors in unbounded LinkedBlockingQueue‑based thread pools, compares their designs, and shows practical code snippets for integrating them into Java projects.

Su San Talks Tech
Su San Talks Tech
Su San Talks Tech
How MemorySafeLBQ Prevents OOM in Java Thread Pools: A Deep Dive

The author, Su San, discovered a pull request named MemorySafeLBQ in an open‑source project and decided to investigate how it claims to be memory‑safe.

Traditional thread pools often use FixedThreadPool or SingleThreadPool with an unbounded LinkedBlockingQueue, whose default capacity is Integer.MAX_VALUE, leading to potential OOM when the queue grows.

MemoryLimitedLBQ is a custom queue that extends LinkedBlockingQueue and adds a memoryLimiter object to enforce a memory limit.

Key fields of the limiter include:

memoryLimit – the maximum allowed memory for the queue.

memory – a LongAdder tracking current memory usage.

acquireLock, notLimited, releaseLock, notEmpty – locks for thread‑safe operations.

inst – an Instrumentation instance used to estimate object size.

The put method calls memoryLimiter.acquireInterruptibly, which obtains the object's size via inst.getObjectSize(e) and checks whether adding it would exceed memoryLimit. If so, the thread waits on notLimited.await(); otherwise it updates memory and proceeds.

while (sum + objectSize >= memoryLimit) {
    notLimited.await();
}

A bug existed because the variable sum was a stale snapshot; the fix replaces it with memory.sum() to always read the latest value.

MemorySafeLBQ also extends LinkedBlockingQueue but takes a different approach: it defines a maxFreeMemory (default 256 MB) and checks the JVM's remaining heap using ManagementFactory.getMemoryMXBean(). The core method hasRemainedMemory returns true only if the free memory exceeds maxFreeMemory, and the queue blocks otherwise.

while (memory.sum() + objectSize >= memoryLimit) {
    notLimited.await();
}

Because MemorySafeLBQ does not rely on Instrumentation, it is simpler to use and considered more practical.

Both queues are framework‑agnostic; their source files can be copied into any Java project and used directly.

In summary, MemoryLimitedLBQ limits the memory consumed by the queue itself, while MemorySafeLBQ limits the overall JVM free memory, offering a safer alternative for preventing OOM in high‑throughput thread‑pool scenarios.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaThreadPoolOpenSourceMemoryManagementOOMlinkedblockingqueue
Su San Talks Tech
Written by

Su San Talks Tech

Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.