0
# JMX Management
1
2
Runtime monitoring and management through JMX MBeans for operational visibility and control.
3
4
## Capabilities
5
6
### HikariPoolMXBean
7
8
Pool statistics and management operations through JMX.
9
10
```java { .api }
11
/**
12
* JMX management interface for HikariCP pool statistics and operations
13
* Provides real-time pool metrics and control operations
14
*/
15
public interface HikariPoolMXBean {
16
17
/**
18
* Get the number of currently idle connections in the pool
19
* Note: Values are transient point-in-time measurements
20
* @return current idle connection count
21
*/
22
int getIdleConnections();
23
24
/**
25
* Get the number of currently active (in-use) connections
26
* Note: Values are transient point-in-time measurements
27
* @return current active connection count
28
*/
29
int getActiveConnections();
30
31
/**
32
* Get total number of connections in the pool (idle + active)
33
* Note: Due to timing, sum of idle + active may not equal total
34
* @return total connection count
35
*/
36
int getTotalConnections();
37
38
/**
39
* Get number of threads waiting for connections from the pool
40
* @return thread count awaiting connections
41
*/
42
int getThreadsAwaitingConnection();
43
44
/**
45
* Evict currently idle connections and mark active connections for eviction
46
* Active connections will be evicted when returned to pool
47
*/
48
void softEvictConnections();
49
50
/**
51
* Suspend the pool - new getConnection() calls will block indefinitely
52
* Requires setAllowPoolSuspension(true) in configuration
53
*/
54
void suspendPool();
55
56
/**
57
* Resume pool operations after suspension
58
* Requires setAllowPoolSuspension(true) in configuration
59
*/
60
void resumePool();
61
}
62
```
63
64
**JMX Management Examples:**
65
66
```java
67
import javax.management.MBeanServer;
68
import javax.management.ObjectName;
69
import java.lang.management.ManagementFactory;
70
71
// Access pool MBean through HikariDataSource
72
HikariDataSource dataSource = new HikariDataSource(config);
73
HikariPoolMXBean poolBean = dataSource.getHikariPoolMXBean();
74
75
// Monitor pool statistics
76
System.out.printf("Pool Status:%n");
77
System.out.printf(" Active: %d%n", poolBean.getActiveConnections());
78
System.out.printf(" Idle: %d%n", poolBean.getIdleConnections());
79
System.out.printf(" Total: %d%n", poolBean.getTotalConnections());
80
System.out.printf(" Waiting: %d%n", poolBean.getThreadsAwaitingConnection());
81
82
// Maintenance operations
83
poolBean.softEvictConnections(); // Force connection refresh
84
85
// Pool suspension for maintenance
86
if (config.isAllowPoolSuspension()) {
87
poolBean.suspendPool();
88
// Perform maintenance
89
poolBean.resumePool();
90
}
91
92
// Access via JMX directly (when registerMbeans=true)
93
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
94
ObjectName poolName = new ObjectName("com.zaxxer.hikari:type=Pool (MyPool)");
95
HikariPoolMXBean proxy = MBeanServerInvocationHandler.newProxyInstance(
96
server, poolName, HikariPoolMXBean.class, false);
97
```
98
99
### HikariConfigMXBean
100
101
Runtime configuration management through JMX.
102
103
```java { .api }
104
/**
105
* JMX management interface for HikariCP runtime configuration
106
* Allows modification of certain properties at runtime
107
*/
108
public interface HikariConfigMXBean {
109
110
/**
111
* Connection timeout configuration
112
*/
113
long getConnectionTimeout();
114
void setConnectionTimeout(long connectionTimeoutMs);
115
116
/**
117
* Validation timeout configuration
118
*/
119
long getValidationTimeout();
120
void setValidationTimeout(long validationTimeoutMs);
121
122
/**
123
* Idle timeout configuration
124
*/
125
long getIdleTimeout();
126
void setIdleTimeout(long idleTimeoutMs);
127
128
/**
129
* Leak detection threshold configuration
130
*/
131
long getLeakDetectionThreshold();
132
void setLeakDetectionThreshold(long leakDetectionThresholdMs);
133
134
/**
135
* Maximum connection lifetime configuration
136
*/
137
long getMaxLifetime();
138
void setMaxLifetime(long maxLifetimeMs);
139
140
/**
141
* Pool sizing configuration
142
*/
143
int getMinimumIdle();
144
void setMinimumIdle(int minIdle);
145
146
int getMaximumPoolSize();
147
void setMaximumPoolSize(int maxPoolSize);
148
149
/**
150
* Runtime credential updates (DataSource-based connections only)
151
*/
152
void setPassword(String password);
153
void setUsername(String username);
154
void setCredentials(Credentials credentials);
155
156
/**
157
* Pool identification
158
*/
159
String getPoolName();
160
161
/**
162
* Catalog configuration (runtime changes require pool suspension)
163
*/
164
String getCatalog();
165
void setCatalog(String catalog);
166
}
167
```
168
169
**Runtime Configuration Examples:**
170
171
```java
172
// Access config MBean through HikariDataSource
173
HikariConfigMXBean configBean = dataSource.getHikariConfigMXBean();
174
175
// Adjust pool size based on load
176
configBean.setMaximumPoolSize(30); // Increase max pool size
177
configBean.setMinimumIdle(10); // Increase minimum idle connections
178
179
// Adjust timeouts for different environments
180
configBean.setConnectionTimeout(60000); // 1 minute for slow networks
181
configBean.setLeakDetectionThreshold(300000); // 5 minutes for long operations
182
183
// Update credentials at runtime (DataSource-based only)
184
configBean.setPassword("newPassword");
185
186
// Monitor current settings
187
System.out.printf("Current pool size: %d-%d%n",
188
configBean.getMinimumIdle(),
189
configBean.getMaximumPoolSize());
190
```
191
192
### JMX Registration
193
194
Enable automatic MBean registration for remote monitoring.
195
196
```java { .api }
197
/**
198
* Enable MBean registration in HikariConfig
199
*/
200
HikariConfig config = new HikariConfig();
201
config.setRegisterMbeans(true); // Enable JMX registration
202
config.setPoolName("MyApp-DB"); // Required for JMX (no ':' allowed)
203
204
HikariDataSource dataSource = new HikariDataSource(config);
205
// MBeans automatically registered with names:
206
// - com.zaxxer.hikari:type=Pool (MyApp-DB)
207
// - com.zaxxer.hikari:type=PoolConfig (MyApp-DB)
208
```
209
210
**JMX Console Access:**
211
212
```java
213
import javax.management.*;
214
import java.lang.management.ManagementFactory;
215
216
public class HikariJMXMonitor {
217
218
public void monitorPool(String poolName) throws Exception {
219
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
220
221
// Pool statistics MBean
222
ObjectName poolObjectName = new ObjectName(
223
"com.zaxxer.hikari:type=Pool (" + poolName + ")");
224
225
// Configuration MBean
226
ObjectName configObjectName = new ObjectName(
227
"com.zaxxer.hikari:type=PoolConfig (" + poolName + ")");
228
229
// Read pool statistics
230
Integer active = (Integer) server.getAttribute(poolObjectName, "ActiveConnections");
231
Integer idle = (Integer) server.getAttribute(poolObjectName, "IdleConnections");
232
Integer total = (Integer) server.getAttribute(poolObjectName, "TotalConnections");
233
234
System.out.printf("Pool Stats - Active: %d, Idle: %d, Total: %d%n", active, idle, total);
235
236
// Invoke management operations
237
server.invoke(poolObjectName, "softEvictConnections", null, null);
238
239
// Update configuration
240
server.setAttribute(configObjectName,
241
new Attribute("MaximumPoolSize", 25));
242
}
243
}
244
```
245
246
### Health Monitoring
247
248
Implement health checks using JMX metrics.
249
250
```java
251
import com.zaxxer.hikari.HikariDataSource;
252
import com.zaxxer.hikari.HikariPoolMXBean;
253
254
public class PoolHealthMonitor {
255
256
private final HikariDataSource dataSource;
257
private final HikariPoolMXBean poolBean;
258
259
public PoolHealthMonitor(HikariDataSource dataSource) {
260
this.dataSource = dataSource;
261
this.poolBean = dataSource.getHikariPoolMXBean();
262
}
263
264
/**
265
* Check overall pool health
266
*/
267
public PoolHealth checkHealth() {
268
if (!dataSource.isRunning()) {
269
return PoolHealth.DOWN;
270
}
271
272
int waiting = poolBean.getThreadsAwaitingConnection();
273
int active = poolBean.getActiveConnections();
274
int total = poolBean.getTotalConnections();
275
276
// Check for connection starvation
277
if (waiting > 0) {
278
return PoolHealth.DEGRADED;
279
}
280
281
// Check for pool exhaustion (>90% utilization)
282
if (total > 0 && (double) active / total > 0.9) {
283
return PoolHealth.WARNING;
284
}
285
286
return PoolHealth.HEALTHY;
287
}
288
289
/**
290
* Get detailed health metrics
291
*/
292
public HealthMetrics getMetrics() {
293
return new HealthMetrics(
294
poolBean.getActiveConnections(),
295
poolBean.getIdleConnections(),
296
poolBean.getTotalConnections(),
297
poolBean.getThreadsAwaitingConnection(),
298
dataSource.isRunning()
299
);
300
}
301
302
public enum PoolHealth {
303
HEALTHY, WARNING, DEGRADED, DOWN
304
}
305
306
public static class HealthMetrics {
307
public final int activeConnections;
308
public final int idleConnections;
309
public final int totalConnections;
310
public final int threadsWaiting;
311
public final boolean isRunning;
312
313
public HealthMetrics(int active, int idle, int total, int waiting, boolean running) {
314
this.activeConnections = active;
315
this.idleConnections = idle;
316
this.totalConnections = total;
317
this.threadsWaiting = waiting;
318
this.isRunning = running;
319
}
320
}
321
}
322
```
323
324
### Automated Pool Management
325
326
Use JMX for automated pool management based on metrics.
327
328
```java
329
import java.util.concurrent.ScheduledExecutorService;
330
import java.util.concurrent.Executors;
331
import java.util.concurrent.TimeUnit;
332
333
public class AutoPoolManager {
334
335
private final HikariDataSource dataSource;
336
private final HikariPoolMXBean poolBean;
337
private final HikariConfigMXBean configBean;
338
private final ScheduledExecutorService scheduler;
339
340
public AutoPoolManager(HikariDataSource dataSource) {
341
this.dataSource = dataSource;
342
this.poolBean = dataSource.getHikariPoolMXBean();
343
this.configBean = dataSource.getHikariConfigMXBean();
344
this.scheduler = Executors.newSingleThreadScheduledExecutor();
345
}
346
347
/**
348
* Start automated pool management
349
*/
350
public void startAutoManagement() {
351
scheduler.scheduleAtFixedRate(this::managePool, 30, 30, TimeUnit.SECONDS);
352
}
353
354
private void managePool() {
355
try {
356
int active = poolBean.getActiveConnections();
357
int total = poolBean.getTotalConnections();
358
int waiting = poolBean.getThreadsAwaitingConnection();
359
int maxSize = configBean.getMaximumPoolSize();
360
361
// Scale up if connections are being waited for
362
if (waiting > 0 && maxSize < 50) {
363
int newMax = Math.min(maxSize + 5, 50);
364
configBean.setMaximumPoolSize(newMax);
365
System.out.printf("Scaled up pool to %d connections%n", newMax);
366
}
367
368
// Scale down if utilization is consistently low
369
else if (total > 10 && active < total * 0.3 && maxSize > 10) {
370
int newMax = Math.max(maxSize - 2, 10);
371
configBean.setMaximumPoolSize(newMax);
372
System.out.printf("Scaled down pool to %d connections%n", newMax);
373
}
374
375
// Refresh connections if pool is idle
376
if (active == 0 && total > 0) {
377
poolBean.softEvictConnections();
378
System.out.println("Refreshed idle connections");
379
}
380
381
} catch (Exception e) {
382
System.err.println("Error in pool management: " + e.getMessage());
383
}
384
}
385
386
public void shutdown() {
387
scheduler.shutdown();
388
}
389
}