|
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; |
@@ -56,27 +57,27 @@ public class GCInspector implements NotificationListener, GCInspectorMXBean |
56 | 57 |
|
57 | 58 | /* |
58 | 59 | * The field from java.nio.Bits that tracks the total number of allocated |
59 | | - * bytes of direct memory requires via ByteBuffer.allocateDirect that have not been GCed. |
| 60 | + * bytes of direct memory requested via ByteBuffer.allocateDirect that have not been GCed. |
60 | 61 | */ |
61 | 62 | final static Field BITS_TOTAL_CAPACITY; |
62 | 63 |
|
63 | | - |
64 | 64 | static |
65 | 65 | { |
66 | | - Field temp = null; |
| 66 | + Class<?> bitsClass = null; |
| 67 | + |
67 | 68 | try |
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 | + bitsClass = Class.forName("java.nio.Bits"); |
73 | 71 | } |
74 | 72 | catch (Throwable t) |
75 | 73 | { |
76 | | - logger.debug("Error accessing field of java.nio.Bits", t); |
77 | | - //Don't care, will just return the dummy value -1 if we can't get at the field in this JVM |
| 74 | + logger.debug("Error returning class of java.nio.Bits", t); |
78 | 75 | } |
79 | | - BITS_TOTAL_CAPACITY = temp; |
| 76 | + |
| 77 | + if (bitsClass != null) |
| 78 | + BITS_TOTAL_CAPACITY = getField(bitsClass, "TOTAL_CAPACITY"); |
| 79 | + else |
| 80 | + BITS_TOTAL_CAPACITY = null; |
80 | 81 | } |
81 | 82 |
|
82 | 83 | static final class State |
@@ -303,28 +304,56 @@ public State getTotalSinceLastCheck() |
303 | 304 | public double[] getAndResetStats() |
304 | 305 | { |
305 | 306 | State state = getTotalSinceLastCheck(); |
306 | | - double[] r = new double[7]; |
| 307 | + double[] r = new double[9]; |
307 | 308 | r[0] = TimeUnit.NANOSECONDS.toMillis(nanoTime() - state.startNanos); |
308 | 309 | r[1] = state.maxRealTimeElapsed; |
309 | 310 | r[2] = state.totalRealTimeElapsed; |
310 | 311 | r[3] = state.sumSquaresRealTimeElapsed; |
311 | 312 | r[4] = state.totalBytesReclaimed; |
312 | 313 | r[5] = state.count; |
313 | | - r[6] = getAllocatedDirectMemory(); |
| 314 | + r[6] = getTotalDirectMemory(); |
314 | 315 |
|
315 | 316 | return r; |
316 | 317 | } |
317 | 318 |
|
318 | | - private static long getAllocatedDirectMemory() |
| 319 | + private static long getTotalDirectMemory() |
| 320 | + { |
| 321 | + return getFieldValue(BITS_TOTAL_CAPACITY, true); |
| 322 | + } |
| 323 | + |
| 324 | + private static Field getField(Class<?> clazz, String fieldName) |
| 325 | + { |
| 326 | + try |
| 327 | + { |
| 328 | + Field field = clazz.getDeclaredField(fieldName); |
| 329 | + field.setAccessible(true); |
| 330 | + return field; |
| 331 | + } |
| 332 | + catch (Throwable t) |
| 333 | + { |
| 334 | + logger.trace("Error accessing field {} of {}", fieldName, clazz.getName(), t); |
| 335 | + // Return null to indicate failure |
| 336 | + return null; |
| 337 | + } |
| 338 | + } |
| 339 | + |
| 340 | + /** |
| 341 | + * Retrieves the value of a Field, handling both regular long fields and AtomicLong fields. |
| 342 | + * |
| 343 | + * @param field the Field to retrieve the value from |
| 344 | + * @param isAtomicLong true if the field is an AtomicLong, false if it's a regular long |
| 345 | + * @return the field value, or -1 if retrieval fails or field is null. |
| 346 | + */ |
| 347 | + private static long getFieldValue(Field field, boolean isAtomicLong) |
319 | 348 | { |
320 | | - if (BITS_TOTAL_CAPACITY == null) return -1; |
| 349 | + if (field == null) return -1; |
321 | 350 | try |
322 | 351 | { |
323 | | - return BITS_TOTAL_CAPACITY.getLong(null); |
| 352 | + return isAtomicLong ? ((AtomicLong) field.get(null)).get() : field.getLong(null); |
324 | 353 | } |
325 | 354 | catch (Throwable t) |
326 | 355 | { |
327 | | - logger.trace("Error accessing field of java.nio.Bits", t); |
| 356 | + logger.trace("Error accessing field value of {}", field.getName(), t); |
328 | 357 | //Don't care how or why we failed to get the value in this JVM. Return -1 to indicate failure |
329 | 358 | return -1; |
330 | 359 | } |
|
0 commit comments