Understanding Java Object Pooling with Commons Pool 2 and HikariCP: Concepts, Configuration, and Performance Testing
This article explains Java object pooling using Commons Pool 2 and HikariCP, covering their core classes, configuration parameters, practical examples with Redis and JDBC, interview questions, and JMH performance benchmarks that demonstrate significant throughput improvements.
In everyday Java development, objects such as threads, database connections, or TCP sockets are expensive to create and destroy, so pooling them can greatly improve performance. This article introduces the generic concepts of object pools and focuses on two widely used implementations: the Apache Commons Pool 2 library and the HikariCP database connection pool.
Commons Pool 2
Overview
Commons Pool 2 provides a generic GenericObjectPool class that manages pooled objects based on a PooledObjectFactory and a GenericObjectPoolConfig . Adding the Maven dependency is straightforward:
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.11.1</version>
</dependency>The core class GenericObjectPool is instantiated with a factory and a configuration:
public GenericObjectPool(
final PooledObjectFactory<T> factory,
final GenericObjectPoolConfig<T> config)Case Study: Redis Jedis
Jedis, a popular Redis client, uses Commons Pool to manage connections. The factory creates PooledObject instances via new DefaultPooledObject<>(obj) . Borrowing an object follows this logic:
public T borrowObject(final Duration borrowMaxWaitDuration) throws Exception {
// ...
while (p == null) {
create = false;
// Try to get from idle queue
p = idleObjects.pollFirst();
// If none, create a new one
if (p == null) {
p = create();
if (p != null) {
create = true;
}
}
// ...
}
// ...
}The pool stores idle objects in a LinkedBlockingDeque , a double‑ended queue.
Key Configuration Parameters
maxTotal – maximum number of objects managed by the pool
maxIdle – maximum number of idle objects
minIdle – minimum number of idle objects
Other important settings include maxWaitMillis (maximum wait time for a borrowed object) and blockWhenExhausted (whether to block when the pool is empty). Test flags such as testOnCreate , testOnBorrow , testOnReturn , and testWhileIdle control validation of pooled objects.
JMH Performance Test
A simple JMH benchmark compares using a JedisPool versus creating a new Jedis instance for each operation. The benchmark code is:
@Fork(2)
@State(Scope.Benchmark)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@BenchmarkMode(Mode.Throughput)
public class JedisPoolVSJedisBenchmark {
JedisPool pool = new JedisPool("localhost", 6379);
@Benchmark
public void testPool() {
Jedis jedis = pool.getResource();
jedis.set("a", UUID.randomUUID().toString());
jedis.close();
}
@Benchmark
public void testJedis() {
Jedis jedis = new Jedis("localhost", 6379);
jedis.set("a", UUID.randomUUID().toString());
jedis.close();
}
// ...
}Results plotted with meta‑chart show that the pooled version achieves roughly five times the throughput of the non‑pooled version.
Database Connection Pool: HikariCP
HikariCP is the default connection pool in Spring Boot and is known for its high performance. It uses a FastList instead of ArrayList , byte‑code optimizations via Javassist , and a lock‑free ConcurrentBag to reduce contention.
Key parameters are maximumPoolSize and minimumIdle . In practice, a pool size of 20‑50 connections is usually sufficient; setting it excessively high can waste resources.
HikariCP relies on Connection.isValid() for validation instead of the many test flags present in Commons Pool.
Result Cache Pool
The article also discusses the similarity between pools and caches, introducing the concept of a "Result Cache Pool" that stores processed results (e.g., compiled JSP classes or static HTML generated from dynamic content) to accelerate subsequent accesses.
Summary
The article covered:
Basics of object pooling with Commons Pool 2
Redis connection pooling via Jedis
Performance gains demonstrated by JMH benchmarks
Advantages and configuration of the HikariCP database connection pool
Interview questions related to pool sizing and timeout settings
Conceptual link between pooling and caching (Result Cache Pool)
Properly configuring pool size, idle limits, and timeout values can dramatically improve system throughput while keeping resource usage under control.
Architect's Guide
Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.