0
# Monitoring and JMX Management
1
2
HikariCP provides comprehensive monitoring and runtime management capabilities through JMX MBeans, enabling real-time pool statistics, configuration tuning, and operational control.
3
4
## Capabilities
5
6
### Pool Statistics Monitoring
7
8
Real-time monitoring of connection pool health and performance through HikariPoolMXBean.
9
10
```java { .api }
11
/**
12
* JMX management interface for pool monitoring
13
*/
14
public interface HikariPoolMXBean {
15
/**
16
* Get the number of currently idle connections in the pool
17
* @return current number of idle connections
18
*/
19
int getIdleConnections();
20
21
/**
22
* Get the number of currently active connections in the pool
23
* @return current number of active (in-use) connections
24
*/
25
int getActiveConnections();
26
27
/**
28
* Get the total number of connections currently in the pool
29
* @return total number of connections in the pool
30
*/
31
int getTotalConnections();
32
33
/**
34
* Get the number of threads awaiting connections from the pool
35
* @return number of threads awaiting a connection from the pool
36
*/
37
int getThreadsAwaitingConnection();
38
39
/**
40
* Evict currently idle connections and mark active connections for eviction
41
*/
42
void softEvictConnections();
43
44
/**
45
* Suspend the pool (blocks getConnection() calls indefinitely)
46
*/
47
void suspendPool();
48
49
/**
50
* Resume the pool (allows getConnection() calls to proceed)
51
*/
52
void resumePool();
53
}
54
```
55
56
### Runtime Configuration Management
57
58
Dynamic configuration changes through HikariConfigMXBean without pool restart.
59
60
```java { .api }
61
/**
62
* JMX management interface for runtime configuration changes
63
*/
64
public interface HikariConfigMXBean {
65
// Timeout configuration (milliseconds)
66
long getConnectionTimeout();
67
void setConnectionTimeout(long connectionTimeoutMs);
68
long getValidationTimeout();
69
void setValidationTimeout(long validationTimeoutMs);
70
long getIdleTimeout();
71
void setIdleTimeout(long idleTimeoutMs);
72
long getLeakDetectionThreshold();
73
void setLeakDetectionThreshold(long leakDetectionThresholdMs);
74
long getMaxLifetime();
75
void setMaxLifetime(long maxLifetimeMs);
76
77
// Pool sizing
78
int getMinimumIdle();
79
void setMinimumIdle(int minIdle);
80
int getMaximumPoolSize();
81
void setMaximumPoolSize(int maxPoolSize);
82
83
// Authentication (DataSource-based connections only)
84
void setPassword(String password);
85
void setUsername(String username);
86
87
// Pool identification
88
String getPoolName();
89
String getCatalog();
90
void setCatalog(String catalog);
91
}
92
```
93
94
**Usage Examples:**
95
96
### Accessing MBeans Programmatically
97
98
```java
99
import com.zaxxer.hikari.HikariDataSource;
100
import com.zaxxer.hikari.HikariConfig;
101
import com.zaxxer.hikari.HikariPoolMXBean;
102
import com.zaxxer.hikari.HikariConfigMXBean;
103
104
// Create and configure DataSource
105
HikariConfig config = new HikariConfig();
106
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
107
config.setUsername("user");
108
config.setPassword("password");
109
config.setMaximumPoolSize(20);
110
config.setPoolName("MyApplicationPool");
111
config.setRegisterMbeans(true); // Enable JMX registration
112
113
HikariDataSource dataSource = new HikariDataSource(config);
114
115
// Access pool monitoring MBean
116
HikariPoolMXBean poolMBean = dataSource.getHikariPoolMXBean();
117
if (poolMBean != null) {
118
System.out.println("Active connections: " + poolMBean.getActiveConnections());
119
System.out.println("Idle connections: " + poolMBean.getIdleConnections());
120
System.out.println("Total connections: " + poolMBean.getTotalConnections());
121
System.out.println("Threads waiting: " + poolMBean.getThreadsAwaitingConnection());
122
}
123
124
// Access configuration MBean
125
HikariConfigMXBean configMBean = dataSource.getHikariConfigMXBean();
126
System.out.println("Pool name: " + configMBean.getPoolName());
127
System.out.println("Connection timeout: " + configMBean.getConnectionTimeout());
128
System.out.println("Max pool size: " + configMBean.getMaximumPoolSize());
129
```
130
131
### Runtime Configuration Changes
132
133
```java
134
// Dynamically adjust pool size based on load
135
HikariConfigMXBean configMBean = dataSource.getHikariConfigMXBean();
136
137
// Increase pool size during peak hours
138
configMBean.setMaximumPoolSize(50);
139
configMBean.setMinimumIdle(10);
140
141
// Adjust timeouts for better responsiveness
142
configMBean.setConnectionTimeout(15000); // 15 seconds
143
configMBean.setIdleTimeout(300000); // 5 minutes
144
145
// Enable leak detection in production
146
configMBean.setLeakDetectionThreshold(120000); // 2 minutes
147
```
148
149
### Pool Control Operations
150
151
```java
152
HikariPoolMXBean poolMBean = dataSource.getHikariPoolMXBean();
153
154
// Soft eviction - evict idle connections, mark active for eviction
155
poolMBean.softEvictConnections();
156
157
// Suspend pool for maintenance
158
poolMBean.suspendPool();
159
try {
160
// Perform maintenance operations
161
// All getConnection() calls will block during this time
162
performMaintenanceOperations();
163
} finally {
164
// Resume normal operations
165
poolMBean.resumePool();
166
}
167
```
168
169
### Monitoring and Alerting
170
171
```java
172
public class HikariPoolMonitor {
173
private final HikariPoolMXBean poolMBean;
174
private final HikariConfigMXBean configMBean;
175
176
public HikariPoolMonitor(HikariDataSource dataSource) {
177
this.poolMBean = dataSource.getHikariPoolMXBean();
178
this.configMBean = dataSource.getHikariConfigMXBean();
179
}
180
181
public PoolHealthStatus checkPoolHealth() {
182
if (poolMBean == null) {
183
return PoolHealthStatus.UNKNOWN;
184
}
185
186
int totalConnections = poolMBean.getTotalConnections();
187
int activeConnections = poolMBean.getActiveConnections();
188
int waitingThreads = poolMBean.getThreadsAwaitingConnection();
189
int maxPoolSize = configMBean.getMaximumPoolSize();
190
191
// Check for pool exhaustion
192
if (waitingThreads > 0) {
193
System.err.println("WARNING: " + waitingThreads + " threads waiting for connections");
194
}
195
196
// Check pool utilization
197
double utilization = (double) activeConnections / maxPoolSize;
198
if (utilization > 0.8) {
199
System.err.println("WARNING: Pool utilization is " + (utilization * 100) + "%");
200
}
201
202
// Check for connection starvation
203
if (totalConnections == maxPoolSize && waitingThreads > 0) {
204
return PoolHealthStatus.EXHAUSTED;
205
}
206
207
if (utilization > 0.9) {
208
return PoolHealthStatus.HIGH_UTILIZATION;
209
}
210
211
return PoolHealthStatus.HEALTHY;
212
}
213
214
public void printPoolStatistics() {
215
System.out.println("=== HikariCP Pool Statistics ===");
216
System.out.println("Pool Name: " + configMBean.getPoolName());
217
System.out.println("Active Connections: " + poolMBean.getActiveConnections());
218
System.out.println("Idle Connections: " + poolMBean.getIdleConnections());
219
System.out.println("Total Connections: " + poolMBean.getTotalConnections());
220
System.out.println("Threads Waiting: " + poolMBean.getThreadsAwaitingConnection());
221
System.out.println("Max Pool Size: " + configMBean.getMaximumPoolSize());
222
System.out.println("Connection Timeout: " + configMBean.getConnectionTimeout() + "ms");
223
System.out.println("Idle Timeout: " + configMBean.getIdleTimeout() + "ms");
224
System.out.println("Max Lifetime: " + configMBean.getMaxLifetime() + "ms");
225
}
226
227
public enum PoolHealthStatus {
228
HEALTHY, HIGH_UTILIZATION, EXHAUSTED, UNKNOWN
229
}
230
}
231
```
232
233
### JMX Remote Monitoring
234
235
```java
236
import javax.management.MBeanServer;
237
import javax.management.ObjectName;
238
import java.lang.management.ManagementFactory;
239
240
// Enable JMX registration (required for remote monitoring)
241
HikariConfig config = new HikariConfig();
242
config.setRegisterMbeans(true);
243
config.setPoolName("MyApp-DB-Pool");
244
// ... other configuration
245
246
HikariDataSource dataSource = new HikariDataSource(config);
247
248
// MBeans will be registered under:
249
// - com.zaxxer.hikari:type=Pool (PoolName=MyApp-DB-Pool)
250
// - com.zaxxer.hikari:type=PoolConfig (PoolName=MyApp-DB-Pool)
251
252
// Access via JMX remotely
253
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
254
ObjectName poolObjectName = new ObjectName("com.zaxxer.hikari:type=Pool (MyApp-DB-Pool)");
255
ObjectName configObjectName = new ObjectName("com.zaxxer.hikari:type=PoolConfig (MyApp-DB-Pool)");
256
257
// Get attributes
258
Integer activeConnections = (Integer) server.getAttribute(poolObjectName, "ActiveConnections");
259
Integer totalConnections = (Integer) server.getAttribute(poolObjectName, "TotalConnections");
260
261
// Invoke operations
262
server.invoke(poolObjectName, "softEvictConnections", null, null);
263
```
264
265
### Health Check Integration
266
267
```java
268
public class HikariHealthCheck {
269
private final HikariDataSource dataSource;
270
private final HikariPoolMXBean poolMBean;
271
272
public HikariHealthCheck(HikariDataSource dataSource) {
273
this.dataSource = dataSource;
274
this.poolMBean = dataSource.getHikariPoolMXBean();
275
}
276
277
public boolean isHealthy() {
278
try {
279
// Check if DataSource is closed
280
if (dataSource.isClosed()) {
281
return false;
282
}
283
284
// Check if pool is running
285
if (!dataSource.isRunning()) {
286
return false;
287
}
288
289
// Check pool statistics
290
if (poolMBean != null) {
291
int totalConnections = poolMBean.getTotalConnections();
292
int waitingThreads = poolMBean.getThreadsAwaitingConnection();
293
294
// Fail health check if no connections available and threads waiting
295
if (totalConnections == 0 && waitingThreads > 0) {
296
return false;
297
}
298
}
299
300
// Test connection acquisition
301
try (Connection connection = dataSource.getConnection()) {
302
return connection.isValid(5); // 5 second timeout
303
}
304
305
} catch (Exception e) {
306
return false;
307
}
308
}
309
}
310
```
311
312
## Monitoring Best Practices
313
314
### JMX Configuration
315
- Always set `registerMbeans(true)` for production monitoring
316
- Use descriptive pool names for multiple pools
317
- Consider JMX security for remote monitoring
318
319
### Health Checks
320
- Monitor connection utilization regularly
321
- Set up alerts for thread starvation
322
- Track connection timeout events
323
324
### Performance Tuning
325
- Monitor pool statistics during load testing
326
- Adjust pool sizes based on actual usage patterns
327
- Use soft eviction for connection refresh
328
329
### Operational Procedures
330
- Use pool suspension for maintenance windows
331
- Monitor leak detection threshold violations
332
- Track connection creation/destruction rates
333
334
## Types
335
336
```java { .api }
337
// Pool statistics snapshot
338
public class PoolStatistics {
339
public final int activeConnections;
340
public final int idleConnections;
341
public final int totalConnections;
342
public final int threadsAwaitingConnection;
343
public final String poolName;
344
345
public PoolStatistics(HikariPoolMXBean poolMBean, HikariConfigMXBean configMBean) {
346
this.activeConnections = poolMBean.getActiveConnections();
347
this.idleConnections = poolMBean.getIdleConnections();
348
this.totalConnections = poolMBean.getTotalConnections();
349
this.threadsAwaitingConnection = poolMBean.getThreadsAwaitingConnection();
350
this.poolName = configMBean.getPoolName();
351
}
352
}
353
```