|
26 | 26 | import java.util.HashMap; |
27 | 27 | import java.util.Map; |
28 | 28 | import java.util.concurrent.TimeUnit; |
| 29 | +import java.util.concurrent.atomic.AtomicLong; |
29 | 30 | import java.util.concurrent.atomic.AtomicReference; |
30 | 31 |
|
31 | 32 | import javax.management.MBeanServer; |
@@ -60,23 +61,20 @@ public class GCInspector implements NotificationListener, GCInspectorMXBean |
60 | 61 | */ |
61 | 62 | final static Field BITS_TOTAL_CAPACITY; |
62 | 63 |
|
63 | | - |
64 | 64 | static |
65 | 65 | { |
66 | | - Field temp = null; |
| 66 | + Field totalTempField = null; |
67 | 67 | try |
68 | 68 | { |
69 | 69 | Class<?> bitsClass = Class.forName("java.nio.Bits"); |
70 | | - Field f = bitsClass.getDeclaredField("TOTAL_CAPACITY"); |
71 | | - f.setAccessible(true); |
72 | | - temp = f; |
| 70 | + totalTempField = getField(bitsClass, "TOTAL_CAPACITY"); |
73 | 71 | } |
74 | 72 | catch (Throwable t) |
75 | 73 | { |
76 | 74 | logger.debug("Error accessing field of java.nio.Bits", t); |
77 | 75 | //Don't care, will just return the dummy value -1 if we can't get at the field in this JVM |
78 | 76 | } |
79 | | - BITS_TOTAL_CAPACITY = temp; |
| 77 | + BITS_TOTAL_CAPACITY = totalTempField; |
80 | 78 | } |
81 | 79 |
|
82 | 80 | static final class State |
@@ -303,28 +301,52 @@ public State getTotalSinceLastCheck() |
303 | 301 | public double[] getAndResetStats() |
304 | 302 | { |
305 | 303 | State state = getTotalSinceLastCheck(); |
306 | | - double[] r = new double[7]; |
| 304 | + double[] r = new double[9]; |
307 | 305 | r[0] = TimeUnit.NANOSECONDS.toMillis(nanoTime() - state.startNanos); |
308 | 306 | r[1] = state.maxRealTimeElapsed; |
309 | 307 | r[2] = state.totalRealTimeElapsed; |
310 | 308 | r[3] = state.sumSquaresRealTimeElapsed; |
311 | 309 | r[4] = state.totalBytesReclaimed; |
312 | 310 | r[5] = state.count; |
313 | | - r[6] = getAllocatedDirectMemory(); |
| 311 | + r[6] = getTotalDirectMemory(); |
314 | 312 |
|
315 | 313 | return r; |
316 | 314 | } |
317 | 315 |
|
318 | | - private static long getAllocatedDirectMemory() |
| 316 | + private static long getTotalDirectMemory() |
319 | 317 | { |
320 | | - if (BITS_TOTAL_CAPACITY == null) return -1; |
| 318 | + return getFieldValue(BITS_TOTAL_CAPACITY, true); |
| 319 | + } |
| 320 | + |
| 321 | + private static Field getField(Class<?> clazz, String fieldName) |
| 322 | + { |
| 323 | + try |
| 324 | + { |
| 325 | + Field field = clazz.getDeclaredField(fieldName); |
| 326 | + field.setAccessible(true); |
| 327 | + return field; |
| 328 | + } |
| 329 | + catch (Throwable t) |
| 330 | + { |
| 331 | + logger.trace("Error accessing field {} of {}", fieldName, clazz.getName(), t); |
| 332 | + // Return null to indicate failure |
| 333 | + return null; |
| 334 | + } |
| 335 | + } |
| 336 | + |
| 337 | + /** |
| 338 | + * This method works well with JDK 11/17 |
| 339 | + */ |
| 340 | + private static long getFieldValue(Field field, boolean isAtomicLong) |
| 341 | + { |
| 342 | + if (field == null) return -1; |
321 | 343 | try |
322 | 344 | { |
323 | | - return BITS_TOTAL_CAPACITY.getLong(null); |
| 345 | + return isAtomicLong ? ((AtomicLong) field.get(null)).get() : field.getLong(null); |
324 | 346 | } |
325 | 347 | catch (Throwable t) |
326 | 348 | { |
327 | | - logger.trace("Error accessing field of java.nio.Bits", t); |
| 349 | + logger.trace("Error accessing field value of {}", field.getName(), t); |
328 | 350 | //Don't care how or why we failed to get the value in this JVM. Return -1 to indicate failure |
329 | 351 | return -1; |
330 | 352 | } |
|
0 commit comments