Master object pooling to reduce garbage collection pause times. Learn when to pool, common patterns, and production pitfalls.
JOptimize Team
Object allocation is expensive. Each object created allocates memory that GC must eventually collect. In high-throughput systems, excessive allocation causes GC pauses that break latency SLAs.
Object pooling reuses objects instead of creating new ones. Pre-allocate objects at startup, hand them out on request, recycle when done.
This guide covers pooling patterns, when to use them, mistakes, and production implementation.
High-frequency allocations:
At 10,000 requests/sec: 650MB/sec allocated. Full GC every 500ms. 50-100ms pause times.
Reuse pre-allocated objects. No allocation garbage. No GC pauses.
Pool these:
Don't pool:
public class ObjectPool<T> { private final Queue<T> available; private final Supplier<T> factory; private final Consumer<T> reset; public ObjectPool(Supplier<T> factory, Consumer<T> reset, int size) { this.factory = factory; this.reset = reset; this.available = new ConcurrentLinkedQueue<>(); for (int i = 0; i < size; i++) { available.offer(factory.get()); } } public T acquire() { T obj = available.poll(); return obj != null ? obj : factory.get(); } public void release(T obj) { reset.accept(obj); available.offer(obj); } }
Production-grade pooling:
GenericObjectPool pool = new GenericObjectPool( new RequestContextFactory(), 10000 // max size ); RequestContext ctx = (RequestContext) pool.borrowObject(); try { process(ctx); } finally { pool.returnObject(ctx); }
Netty pools buffers automatically:
ByteBufAllocator allocator = PooledByteBufAllocator.DEFAULT; ByteBuf buf = allocator.buffer(1024); try { // Use buffer } finally { buf.release(); // Returns to pool }
Pool leaks data if objects aren't cleared before returning.
Pool exhaustion causes on-demand allocation - defeats the purpose.
Other threads blocked waiting for available objects.
Object pooling eliminates allocation overhead for high-frequency objects. Use it for buffers, contexts, frequently-created objects.
Benefits: reduced GC pauses, lower latency, predictable performance.
Costs: memory overhead, state management complexity.
Worth it when allocation is a measured bottleneck.
Object pooling is one solution. Missing indexes, unbounded collections, inefficient queries also cause memory spikes.
JOptimize detects allocation hotspots:
Use code LINKEDIN40 for 40% OFF JOptimize PRO.
Pool objects. Eliminate GC pauses. Achieve predictable latency.
Master Spring Boot, security, and Java performance with hands-on courses.
JOptimize finds N+1 queries, EAGER collections, and 70+ other issues in your Java codebase — in under 30 seconds.