001/*
002 * Copyright 2008-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2018 Ping Identity Corporation
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.ldap.sdk.unboundidds.monitors;
022
023
024
025import java.util.ArrayList;
026import java.util.Collections;
027import java.util.LinkedHashMap;
028import java.util.List;
029import java.util.Map;
030import java.util.TreeMap;
031import java.util.TreeSet;
032
033import com.unboundid.ldap.sdk.Attribute;
034import com.unboundid.ldap.sdk.Entry;
035import com.unboundid.util.NotMutable;
036import com.unboundid.util.ThreadSafety;
037import com.unboundid.util.ThreadSafetyLevel;
038
039import static com.unboundid.ldap.sdk.unboundidds.monitors.MonitorMessages.*;
040import static com.unboundid.util.Debug.*;
041import static com.unboundid.util.StaticUtils.*;
042
043
044
045/**
046 * This class defines a monitor entry that provides information about the memory
047 * usage for the JVM in which the Directory Server is running.  In particular,
048 * it reports information about the memory pools and garbage collectors defined
049 * in the JVM.
050 * <BR>
051 * <BLOCKQUOTE>
052 *   <B>NOTE:</B>  This class, and other classes within the
053 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
054 *   supported for use against Ping Identity, UnboundID, and Alcatel-Lucent 8661
055 *   server products.  These classes provide support for proprietary
056 *   functionality or for external specifications that are not considered stable
057 *   or mature enough to be guaranteed to work in an interoperable way with
058 *   other types of LDAP servers.
059 * </BLOCKQUOTE>
060 * <BR>
061 * The information that may be available in the memory usage monitor entry
062 * includes:
063 * <UL>
064 *   <LI>The names of the memory pools that are in use within the JVM.</LI>
065 *   <LI>The number of bytes currently used within each memory pool.</LI>
066 *   <LI>The number of bytes used within each memory pool after the last
067 *       garbage collection.</LI>
068 *   <LI>The names of the garbage collectors that are in use within the
069 *       JVM.</LI>
070 *   <LI>The number of garbage collections performed by each collector.</LI>
071 *   <LI>The total duration of all garbage collections performed by each
072 *       collector.</LI>
073 *   <LI>The average duration of garbage collections performed by each
074 *       collector.</LI>
075 *   <LI>The duration of the most recent garbage collection performed by each
076 *       collector.</LI>
077 *   <LI>The amount of non-heap memory consumed by the JVM.</LI>
078 *   <LI>The number of detected pauses of various durations detected by the
079 *       server.</LI>
080 *   <LI>The duration of the longest pause detected by the server.</LI>
081 * </UL>
082 * The server should present at most one memory usage monitor entry.  It can be
083 * retrieved using the {@link MonitorManager#getMemoryUsageMonitorEntry} method.
084 * This entry provides specific methods for accessing information about JVM
085 * memory usage (e.g., the {@link MemoryUsageMonitorEntry#getMemoryPoolNames}
086 * method can be used to retrieve the names of the memory pool).  Alternately,
087 * this information may be accessed using the generic API.  See the
088 * {@link MonitorManager} class documentation for an example that demonstrates
089 * the use of the generic API for accessing monitor data.
090 */
091@NotMutable()
092@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
093public final class MemoryUsageMonitorEntry
094       extends MonitorEntry
095{
096  /**
097   * The structural object class used in memory usage monitor entries.
098   */
099  static final String MEMORY_USAGE_MONITOR_OC =
100       "ds-memory-usage-monitor-entry";
101
102
103
104  /**
105   * The name of the attribute that holds the duration of the longest detected
106   * pause.
107   */
108  private static final String ATTR_LONGEST_PAUSE_TIME =
109       "max-detected-pause-time-millis";
110
111
112
113  /**
114   * The name of the attribute that holds the amount of non-heap memory used
115   * by the JVM.
116   */
117  private static final String ATTR_NON_HEAP_USED = "non-heap-memory-bytes-used";
118
119
120
121  /**
122   * The name of the attribute that holds the total amount of memory used by
123   * memory consumers.
124   */
125  private static final String ATTR_TOTAL_CONSUMER_MEMORY =
126       "total-bytes-used-by-memory-consumers";
127
128
129
130  /**
131   * The name of the attribute that holds the percentage of committed tenured
132   * memory held by memory consumers.
133   */
134  private static final String ATTR_TOTAL_CONSUMER_MEMORY_AS_PCT_OF_COMMITTED =
135       "memory-consumers-total-as-percent-of-committed-tenured-memory";
136
137
138
139  /**
140   * The name of the attribute that holds the percentage of maximum allowed
141   * tenured memory held by memory consumers.
142   */
143  private static final String ATTR_TOTAL_CONSUMER_MEMORY_AS_PCT_OF_MAX =
144       "memory-consumers-total-as-percent-of-maximum-tenured-memory";
145
146
147
148  /**
149   * The prefix that will be used for pauses detected by the server.
150   */
151  private static final String ATTR_PREFIX_DETECTED_PAUSE =
152       "detected-pauses-over-";
153
154
155
156  /**
157   * The suffix that will be used for attributes providing the total collection
158   * count for a garbage collector.
159   */
160  private static final String ATTR_SUFFIX_TOTAL_COLLECTION_COUNT =
161       "-total-collection-count";
162
163
164
165  /**
166   * The suffix that will be used for attributes providing the total collection
167   * duration for a garbage collector.
168   */
169  private static final String ATTR_SUFFIX_TOTAL_COLLECTION_DURATION =
170       "-total-collection-duration";
171
172
173
174  /**
175   * The suffix that will be used for attributes providing the average
176   * collection duration for a garbage collector.
177   */
178  private static final String ATTR_SUFFIX_AVERAGE_COLLECTION_DURATION =
179       "-average-collection-duration";
180
181
182
183  /**
184   * The suffix that will be used for attributes providing the recent collection
185   * duration for a garbage collector.
186   */
187  private static final String ATTR_SUFFIX_RECENT_COLLECTION_DURATION =
188       "-recent-collection-duration";
189
190
191
192  /**
193   * The suffix that will be used for attributes providing the current bytes
194   * used in a memory pool.
195   */
196  private static final String ATTR_SUFFIX_CURRENT_BYTES_USED =
197       "-current-bytes-used";
198
199
200
201  /**
202   * The suffix that will be used for attributes providing the bytes used after
203   * the last collection in a memory pool.
204   */
205  private static final String ATTR_SUFFIX_BYTES_USED_AFTER_LAST_COLLECTION =
206       "-bytes-used-after-last-collection";
207
208
209
210  /**
211   * The name of the property used to provide the numbers of pauses of various
212   * durations detected.
213   */
214  private static final String PROPERTY_DETECTED_PAUSE_COUNTS =
215       "detected-pause-counts";
216
217
218
219  /**
220   * The name of the attribute that holds the maximum amount of memory that may
221   * be used by the JVM, in megabytes.
222   */
223  private static final String ATTR_MAX_RESERVABLE_MEMORY_MB =
224       "maxReservableMemoryMB";
225
226
227
228  /**
229   * The name of the attribute that holds the amount of memory currently
230   * allocated for use by the JVM, in megabytes.
231   */
232  private static final String ATTR_CURRENT_RESERVED_MEMORY_MB =
233       "currentReservedMemoryMB";
234
235
236
237  /**
238   * The name of the attribute that holds the amount of allocated JVM memory
239   * which is actually in use.
240   */
241  private static final String ATTR_USED_MEMORY_MB = "usedReservedMemoryMB";
242
243
244
245  /**
246   * The name of the attribute that holds the amount of allocated JVM memory
247   * that is not currently in use.
248   */
249  private static final String ATTR_FREE_MEMORY_MB = "freeReservedMemoryMB";
250
251
252
253  /**
254   * The name of the attribute that holds the percentage of the maximum JVM
255   * memory that is actually in use.
256   */
257  private static final String ATTR_RESERVED_MEMORY_PERCENT_FULL =
258       "reservedMemoryPercentFull";
259
260
261
262  /**
263   * The serial version UID for this serializable class.
264   */
265  private static final long serialVersionUID = 1924052253885937441L;
266
267
268
269  // The list of garbage collectors for which information is available.
270  private final List<String> garbageCollectors;
271
272  // The list of memory pools for which information is available.
273  private final List<String> memoryPools;
274
275  // The amount of memory that has currently been allocated by the JVM, in
276  // megabytes.
277  private final Long currentReservedMemoryMB;
278
279  // The amount of allocated JVM memory that is not currently in use, in
280  // megabytes.
281  private final Long freeReservedMemoryMB;
282
283  // The maximum pause time detected by the JVM.
284  private final Long maxDetectedPauseTime;
285
286  // The maximum amount of memory that may be used by the JVM, in megabytes.
287  private final Long maxReservableMemoryMB;
288
289  // The amount of non-heap memory consumed by the JVM.
290  private final Long nonHeapMemoryUsed;
291
292  // The percentage of committed tenured memory held by consumers.
293  private final Long percentOfCommittedTenuredMemory;
294
295  // The percentage of maximum tenured memory held by consumers.
296  private final Long percentOfMaxTenuredMemory;
297
298  // The percentage of the maximum JVM memory that is currently in use.
299  private final Long reservedMemoryPercentFull;
300
301  // The total amount of memory held by memory consumers.
302  private final Long totalBytesHeldByConsumers;
303
304  // The amount of allocated JVM memory that is currently in use, in megabytes.
305  private final Long usedReservedMemoryMB;
306
307  // The number of pauses exceeding specified thresholds.
308  private final Map<Long,Long> detectedPauses;
309
310  // The list of bytes used after the last collection per memory pool.
311  private final Map<String,Long> bytesUsedAfterLastCollectionPerMP;
312
313  // The list of current bytes used per memory pool.
314  private final Map<String,Long> currentBytesUsedPerMP;
315
316  // The list of average collection durations per garbage collector.
317  private final Map<String,Long> averageCollectionDurationPerGC;
318
319  // The list of recent collection durations per garbage collector.
320  private final Map<String,Long> recentCollectionDurationPerGC;
321
322  // The list of total collection counts per garbage collector.
323  private final Map<String,Long> totalCollectionCountPerGC;
324
325  // The list of total collection durations per garbage collector.
326  private final Map<String,Long> totalCollectionDurationPerGC;
327
328
329
330  /**
331   * Creates a new memory usage monitor entry from the provided entry.
332   *
333   * @param  entry  The entry to be parsed as a memory usage monitor entry.  It
334   *                must not be {@code null}.
335   */
336  public MemoryUsageMonitorEntry(final Entry entry)
337  {
338    super(entry);
339
340    maxDetectedPauseTime            = getLong(ATTR_LONGEST_PAUSE_TIME);
341    nonHeapMemoryUsed               = getLong(ATTR_NON_HEAP_USED);
342    totalBytesHeldByConsumers       = getLong(ATTR_TOTAL_CONSUMER_MEMORY);
343    percentOfCommittedTenuredMemory =
344         getLong(ATTR_TOTAL_CONSUMER_MEMORY_AS_PCT_OF_COMMITTED);
345    percentOfMaxTenuredMemory =
346         getLong(ATTR_TOTAL_CONSUMER_MEMORY_AS_PCT_OF_MAX);
347
348    maxReservableMemoryMB     = getLong(ATTR_MAX_RESERVABLE_MEMORY_MB);
349    currentReservedMemoryMB   = getLong(ATTR_CURRENT_RESERVED_MEMORY_MB);
350    usedReservedMemoryMB      = getLong(ATTR_USED_MEMORY_MB);
351    freeReservedMemoryMB      = getLong(ATTR_FREE_MEMORY_MB);
352    reservedMemoryPercentFull = getLong(ATTR_RESERVED_MEMORY_PERCENT_FULL);
353
354
355    final TreeMap<Long,Long> pauses = new TreeMap<Long,Long>();
356
357    final TreeSet<String> mpNames = new TreeSet<String>();
358    final TreeSet<String> gcNames = new TreeSet<String>();
359
360    final TreeMap<String,Long> averageDurations = new TreeMap<String,Long>();
361    final TreeMap<String,Long> currentBytesUsed = new TreeMap<String,Long>();
362    final TreeMap<String,Long> lastBytesUsed    = new TreeMap<String,Long>();
363    final TreeMap<String,Long> recentDurations  = new TreeMap<String,Long>();
364    final TreeMap<String,Long> totalCounts      = new TreeMap<String,Long>();
365    final TreeMap<String,Long> totalDurations   = new TreeMap<String,Long>();
366
367    for (final Attribute a : entry.getAttributes())
368    {
369      final String name      = a.getName();
370      final String lowerName = toLowerCase(name);
371
372      if (lowerName.startsWith(ATTR_PREFIX_DETECTED_PAUSE))
373      {
374        final Long l = getLong(name);
375
376        final String timeStr =
377             lowerName.substring(ATTR_PREFIX_DETECTED_PAUSE.length());
378        if (timeStr.endsWith("ms"))
379        {
380          try
381          {
382            final long millis =
383                 Long.parseLong(timeStr.substring(0, timeStr.length()-2));
384            pauses.put(millis, l);
385          }
386          catch (final Exception e)
387          {
388            debugException(e);
389          }
390        }
391        else if (timeStr.endsWith("s"))
392        {
393          try
394          {
395            final long millis = 1000 *
396                 Long.parseLong(timeStr.substring(0, timeStr.length()-1));
397            pauses.put(millis, l);
398          }
399          catch (final Exception e)
400          {
401            debugException(e);
402          }
403        }
404      }
405
406      int pos = lowerName.indexOf(ATTR_SUFFIX_AVERAGE_COLLECTION_DURATION);
407      if (pos > 0)
408      {
409        final String gcName = name.substring(0, pos);
410        gcNames.add(gcName);
411
412        final Long l = getLong(name);
413        if (l != null)
414        {
415          averageDurations.put(toLowerCase(gcName), l);
416        }
417
418        continue;
419      }
420
421      pos = lowerName.indexOf(ATTR_SUFFIX_BYTES_USED_AFTER_LAST_COLLECTION);
422      if (pos > 0)
423      {
424        final String mpName = name.substring(0, pos);
425        mpNames.add(mpName);
426
427        final Long l = getLong(name);
428        if (l != null)
429        {
430          lastBytesUsed.put(toLowerCase(mpName), l);
431        }
432
433        continue;
434      }
435
436      pos = lowerName.indexOf(ATTR_SUFFIX_CURRENT_BYTES_USED);
437      if (pos > 0)
438      {
439        final String mpName = name.substring(0, pos);
440        mpNames.add(mpName);
441
442        final Long l = getLong(name);
443        if (l != null)
444        {
445          currentBytesUsed.put(toLowerCase(mpName), l);
446        }
447
448        continue;
449      }
450
451      pos = lowerName.indexOf(ATTR_SUFFIX_RECENT_COLLECTION_DURATION);
452      if (pos > 0)
453      {
454        final String gcName = name.substring(0, pos);
455        gcNames.add(gcName);
456
457        final Long l = getLong(name);
458        if (l != null)
459        {
460          recentDurations.put(toLowerCase(gcName), l);
461        }
462
463        continue;
464      }
465
466      pos = lowerName.indexOf(ATTR_SUFFIX_TOTAL_COLLECTION_COUNT);
467      if ((pos > 0) && (! lowerName.startsWith("mem-pool-")))
468      {
469        final String gcName = name.substring(0, pos);
470        gcNames.add(gcName);
471
472        final Long l = getLong(name);
473        if (l != null)
474        {
475          totalCounts.put(toLowerCase(gcName), l);
476        }
477
478        continue;
479      }
480
481      pos = lowerName.indexOf(ATTR_SUFFIX_TOTAL_COLLECTION_DURATION);
482      if (pos > 0)
483      {
484        final String gcName = name.substring(0, pos);
485        gcNames.add(gcName);
486
487        final Long l = getLong(name);
488        if (l != null)
489        {
490          totalDurations.put(toLowerCase(gcName), l);
491        }
492
493        continue;
494      }
495    }
496
497
498    garbageCollectors =
499         Collections.unmodifiableList(new ArrayList<String>(gcNames));
500
501    memoryPools = Collections.unmodifiableList(new ArrayList<String>(mpNames));
502
503    totalCollectionCountPerGC = Collections.unmodifiableMap(totalCounts);
504
505    totalCollectionDurationPerGC = Collections.unmodifiableMap(totalDurations);
506
507    averageCollectionDurationPerGC =
508         Collections.unmodifiableMap(averageDurations);
509
510    recentCollectionDurationPerGC =
511         Collections.unmodifiableMap(recentDurations);
512
513    bytesUsedAfterLastCollectionPerMP =
514         Collections.unmodifiableMap(lastBytesUsed);
515
516    currentBytesUsedPerMP = Collections.unmodifiableMap(currentBytesUsed);
517
518    detectedPauses = Collections.unmodifiableMap(pauses);
519  }
520
521
522
523  /**
524   * Retrieves the maximum amount of memory (in megabytes) that may be allocated
525   * and used by the JVM.
526   *
527   * @return  The maximum amount of memory (in megabytes) that may be allocated
528   *          and used by the JVM, or {@code null} if this was not included in
529   *          the monitor entry.
530   */
531  public Long getMaxReservableMemoryMB()
532  {
533    return maxReservableMemoryMB;
534  }
535
536
537
538  /**
539   * Retrieves the amount of memory (in megabytes) that is currently allocated
540   * for use by the JVM.
541   *
542   * @return  The amount of memory (in megabytes) that is currently allocated
543   *          for use by the JVM, or {@code null} if this was not included in
544   *          the monitor entry.
545   */
546  public Long getCurrentReservedMemoryMB()
547  {
548    return currentReservedMemoryMB;
549  }
550
551
552
553  /**
554   * Retrieves the amount of memory (in megabytes) allocated for use by the JVM
555   * that is currently in use for holding Java objects.
556   *
557   * @return  The amount of memory (in megabytes) allocated for use by the JVM
558   *          that is currently in use for holding Java objects, or {@code null}
559   *          if this was not included in the monitor entry.
560   */
561  public Long getUsedReservedMemoryMB()
562  {
563    return usedReservedMemoryMB;
564  }
565
566
567
568  /**
569   * Retrieves the amount of memory (in megabytes) allocated for use by the JVM
570   * that is not currently in use for holding Java objects.
571   *
572   * @return  The amount of memory (in megabytes) allocated for use by the JVM
573   *          that is not currently in use for holding Java objects, or
574   *          {@code null} if this was not included in the monitor entry.
575   */
576  public Long getFreeReservedMemoryMB()
577  {
578    return freeReservedMemoryMB;
579  }
580
581
582
583  /**
584   * Retrieves the percent of the currently-reserved memory that is actually in
585   * use by the JVM for storing Java objects.
586   *
587   * @return  The percent of the currently-reserved memory that is actually in
588   *          use by the JVM for storing Java objects.
589   */
590  public Long getReservedMemoryPercentFull()
591  {
592    return reservedMemoryPercentFull;
593  }
594
595
596
597  /**
598   * Retrieves the names of the garbage collectors for which information is
599   * available.
600   *
601   * @return  The names of the garbage collectors for which information is
602   *          available.
603   */
604  public List<String> getGarbageCollectorNames()
605  {
606    return garbageCollectors;
607  }
608
609
610
611  /**
612   * Retrieves the names of the memory pools for which information is available.
613   *
614   * @return  The names of the memory pools for which information is available.
615   */
616  public List<String> getMemoryPoolNames()
617  {
618    return memoryPools;
619  }
620
621
622
623  /**
624   * Retrieves a map containing the total number of garbage collections
625   * performed per collector.
626   *
627   * @return  A map containing the total number of garbage collections performed
628   *          per collector.
629   */
630  public Map<String,Long> getTotalCollectionCounts()
631  {
632    return totalCollectionCountPerGC;
633  }
634
635
636
637  /**
638   * Retrieves the total number of garbage collections performed by the
639   * specified collector.
640   *
641   * @param  collectorName  The name of the garbage collector for which to
642   *                        retrieve the information.
643   *
644   * @return  The total number of garbage collections performed by the specified
645   *          collector, or {@code null} if that information is not available.
646   */
647  public Long getTotalCollectionCount(final String collectorName)
648  {
649    return totalCollectionCountPerGC.get(toLowerCase(collectorName));
650  }
651
652
653
654  /**
655   * Retrieves a map containing the total length of time (in milliseconds) spent
656   * performing garbage collection per collector.
657   *
658   * @return  A map containing the total length of time (in milliseconds) spent
659   *          performing garbage collection per collector.
660   */
661  public Map<String,Long> getTotalCollectionDurations()
662  {
663    return totalCollectionDurationPerGC;
664  }
665
666
667
668  /**
669   * Retrieves the total length of time (in milliseconds) spent performing
670   * garbage collection for the specified collector.
671   *
672   * @param  collectorName  The name of the garbage collector for which to
673   *                        retrieve the information.
674   *
675   * @return  The total length of time (in milliseconds) spent performing
676   *          garbage collection for the specified collector, or {@code null} if
677   *          that information is not available.
678   */
679  public Long getTotalCollectionDuration(final String collectorName)
680  {
681    return totalCollectionDurationPerGC.get(toLowerCase(collectorName));
682  }
683
684
685
686  /**
687   * Retrieves a map containing the average garbage collection duration (in
688   * milliseconds) per garbage collector.
689   *
690   * @return  A map containing the average garbage collection duration (in
691   *          milliseconds) per garbage collector.
692   */
693  public Map<String,Long> getAverageCollectionDurations()
694  {
695    return averageCollectionDurationPerGC;
696  }
697
698
699
700  /**
701   * Retrieves the average garbage collection duration (in milliseconds) for the
702   * specified collector.
703   *
704   * @param  collectorName  The name of the garbage collector for which to
705   *                        retrieve the information.
706   *
707   * @return  The average garbage collection duration (in milliseconds) for the
708   *          specified collector, or {@code null} if that information is not
709   *          available.
710   */
711  public Long getAverageCollectionDuration(final String collectorName)
712  {
713    return averageCollectionDurationPerGC.get(toLowerCase(collectorName));
714  }
715
716
717
718  /**
719   * Retrieves a map containing the most recent garbage collection duration (in
720   * milliseconds) per garbage collector.
721   *
722   * @return  A map containing the duration of the most recent garbage
723   *          collection duration (in milliseconds) per garbage collector.
724   */
725  public Map<String,Long> getRecentCollectionDurations()
726  {
727    return recentCollectionDurationPerGC;
728  }
729
730
731
732  /**
733   * Retrieves the duration (in milliseconds) of the most recent garbage
734   * collection for the specified collector.
735   *
736   * @param  collectorName  The name of the garbage collector for which to
737   *                        retrieve the information.
738   *
739   * @return  The duration (in milliseconds) of the most recent garbage
740   *          collection for the specified collector, or {@code null} if that
741   *          information is not available.
742   */
743  public Long getRecentCollectionDuration(final String collectorName)
744  {
745    return recentCollectionDurationPerGC.get(toLowerCase(collectorName));
746  }
747
748
749
750  /**
751   * Retrieves a map containing the current number of bytes used per memory
752   * pool.
753   *
754   * @return  A map containing the current number of bytes used per memory pool.
755   */
756  public Map<String,Long> getCurrentBytesUsed()
757  {
758    return currentBytesUsedPerMP;
759  }
760
761
762
763  /**
764   * Retrieves the current number of bytes used for the specified memory pool.
765   *
766   * @param  poolName  The name of the memory pool for which to retrieve the
767   *                   information.
768   *
769   * @return  The current number of bytes used for the specified memory pool, or
770   *          {@code null} if that information is not available.
771   */
772  public Long getCurrentBytesUsed(final String poolName)
773  {
774    return currentBytesUsedPerMP.get(toLowerCase(poolName));
775  }
776
777
778
779  /**
780   * Retrieves a map containing the number of bytes used after the last garbage
781   * collection per memory pool.
782   *
783   * @return  A map containing the number of bytes used after the last garbage
784   *          collection per memory pool.
785   */
786  public Map<String,Long> getBytesUsedAfterLastCollection()
787  {
788    return bytesUsedAfterLastCollectionPerMP;
789  }
790
791
792
793  /**
794   * Retrieves the number of bytes used after the last garbage collection for
795   * the specified memory pool.
796   *
797   * @param  poolName  The name of the memory pool for which to retrieve the
798   *                   information.
799   *
800   * @return  The number of bytes used after the last garbage collection for the
801   *          specified memory pool, or {@code null} if that information is not
802   *          available.
803   */
804  public Long getBytesUsedAfterLastCollection(final String poolName)
805  {
806    return bytesUsedAfterLastCollectionPerMP.get(toLowerCase(poolName));
807  }
808
809
810
811  /**
812   * Retrieves the amount of non-heap memory consumed by the JVM.
813   *
814   * @return  The amount of non-heap memory consumed by the JVM, or {@code null}
815   *          if that information is not available.
816   */
817  public Long getNonHeapMemoryBytesUsed()
818  {
819    return nonHeapMemoryUsed;
820  }
821
822
823
824  /**
825   * Retrieves the total amount of memory in bytes held by memory consumers.
826   *
827   * @return  The total amount of memory in bytes held by memory consumers, or
828   *          {@code null} if that information is not available.
829   */
830  public Long getTotalBytesUsedByMemoryConsumers()
831  {
832    return totalBytesHeldByConsumers;
833  }
834
835
836
837  /**
838   * Retrieves the percentage of the maximum allowed amount of tenured memory
839   * that is used by memory consumers (assuming that all memory used by memory
840   * consumers is contained in the tenured generation).
841   *
842   * @return  The percentage of the maximum allowed amount of tenured memory
843   *          that is used by memory consumers, or {@code null} if that
844   *          information is not available.
845   */
846  public Long getPercentageOfMaximumTenuredMemoryUsedByMemoryConsumers()
847  {
848    return percentOfMaxTenuredMemory;
849  }
850
851
852
853  /**
854   * Retrieves the percentage of the committed amount of tenured memory that is
855   * used by memory consumers (assuming that all memory used by memory consumers
856   * is contained in the tenured generation).
857   *
858   * @return  The percentage of the committed amount of tenured memory that is
859   *          used by memory consumers, or {@code null} if that information is
860   *          not available.
861   */
862  public Long getPercentageOfCommittedTenuredMemoryUsedByMemoryConsumers()
863  {
864    return percentOfCommittedTenuredMemory;
865  }
866
867
868
869  /**
870   * Retrieves the number of pauses of various durations detected by the server.
871   * The value returned will contain a map between the minimum duration in
872   * milliseconds for the associated bucket and the number of pauses detected of
873   * at least that duration.
874   *
875   * @return  The number of pauses of various durations detected by the server.
876   */
877  public Map<Long,Long> getDetectedPauseCounts()
878  {
879    return detectedPauses;
880  }
881
882
883
884  /**
885   * Retrieves the duration of the longest pause detected by the server.
886   *
887   * @return  The duration of the longest pause detected by the server, or
888   *          {@code null} if that information is not available.
889   */
890  public Long getMaxDetectedPauseTimeMillis()
891  {
892    return maxDetectedPauseTime;
893  }
894
895
896
897  /**
898   * {@inheritDoc}
899   */
900  @Override()
901  public String getMonitorDisplayName()
902  {
903    return INFO_MEMORY_USAGE_MONITOR_DISPNAME.get();
904  }
905
906
907
908  /**
909   * {@inheritDoc}
910   */
911  @Override()
912  public String getMonitorDescription()
913  {
914    return INFO_MEMORY_USAGE_MONITOR_DESC.get();
915  }
916
917
918
919  /**
920   * {@inheritDoc}
921   */
922  @Override()
923  public Map<String,MonitorAttribute> getMonitorAttributes()
924  {
925    final LinkedHashMap<String,MonitorAttribute> attrs =
926         new LinkedHashMap<String,MonitorAttribute>();
927
928    if (maxReservableMemoryMB != null)
929    {
930      addMonitorAttribute(attrs,
931           ATTR_MAX_RESERVABLE_MEMORY_MB,
932           INFO_MEMORY_USAGE_DISPNAME_MAX_MEM.get(),
933           INFO_MEMORY_USAGE_DESC_MAX_MEM.get(),
934           maxReservableMemoryMB);
935    }
936
937    if (currentReservedMemoryMB != null)
938    {
939      addMonitorAttribute(attrs,
940           ATTR_CURRENT_RESERVED_MEMORY_MB,
941           INFO_MEMORY_USAGE_DISPNAME_CURRENT_MEM.get(),
942           INFO_MEMORY_USAGE_DESC_CURRENT_MEM.get(),
943           currentReservedMemoryMB);
944    }
945
946    if (usedReservedMemoryMB != null)
947    {
948      addMonitorAttribute(attrs,
949           ATTR_USED_MEMORY_MB,
950           INFO_MEMORY_USAGE_DISPNAME_USED_MEM.get(),
951           INFO_MEMORY_USAGE_DESC_USED_MEM.get(),
952           usedReservedMemoryMB);
953    }
954
955    if (freeReservedMemoryMB != null)
956    {
957      addMonitorAttribute(attrs,
958           ATTR_FREE_MEMORY_MB,
959           INFO_MEMORY_USAGE_DISPNAME_FREE_MEM.get(),
960           INFO_MEMORY_USAGE_DESC_FREE_MEM.get(),
961           freeReservedMemoryMB);
962    }
963
964    if (reservedMemoryPercentFull != null)
965    {
966      addMonitorAttribute(attrs,
967           ATTR_RESERVED_MEMORY_PERCENT_FULL,
968           INFO_MEMORY_USAGE_DISPNAME_RESERVED_PCT.get(),
969           INFO_MEMORY_USAGE_DESC_RESERVED_PCT.get(),
970           reservedMemoryPercentFull);
971    }
972
973    if (! garbageCollectors.isEmpty())
974    {
975      addMonitorAttribute(attrs,
976           "gcNames",
977           INFO_MEMORY_USAGE_DISPNAME_GC_NAMES.get(),
978           INFO_MEMORY_USAGE_DESC_GC_NAMES.get(),
979           garbageCollectors);
980    }
981
982    if (! totalCollectionCountPerGC.isEmpty())
983    {
984      for (final String name : totalCollectionCountPerGC.keySet())
985      {
986        addMonitorAttribute(attrs,
987            "totalCollectionCount-" + name,
988            INFO_MEMORY_USAGE_DISPNAME_TOTAL_COLLECTION_COUNT.get(name),
989            INFO_MEMORY_USAGE_DESC_TOTAL_COLLECTION_COUNT.get(name),
990            totalCollectionCountPerGC.get(name));
991      }
992    }
993
994    if (! totalCollectionDurationPerGC.isEmpty())
995    {
996      for (final String name : totalCollectionDurationPerGC.keySet())
997      {
998        addMonitorAttribute(attrs,
999            "totalCollectionDuration-" + name,
1000            INFO_MEMORY_USAGE_DISPNAME_TOTAL_COLLECTION_DURATION.get(name),
1001            INFO_MEMORY_USAGE_DESC_TOTAL_COLLECTION_DURATION.get(name),
1002            totalCollectionDurationPerGC.get(name));
1003      }
1004    }
1005
1006    if (! averageCollectionDurationPerGC.isEmpty())
1007    {
1008      for (final String name : averageCollectionDurationPerGC.keySet())
1009      {
1010        addMonitorAttribute(attrs,
1011            "averageCollectionDuration-" + name,
1012            INFO_MEMORY_USAGE_DISPNAME_AVERAGE_COLLECTION_DURATION.get(name),
1013            INFO_MEMORY_USAGE_DESC_AVERAGE_COLLECTION_DURATION.get(name),
1014            averageCollectionDurationPerGC.get(name));
1015      }
1016    }
1017
1018    if (! recentCollectionDurationPerGC.isEmpty())
1019    {
1020      for (final String name : recentCollectionDurationPerGC.keySet())
1021      {
1022        addMonitorAttribute(attrs,
1023            "recentCollectionDuration-" + name,
1024            INFO_MEMORY_USAGE_DISPNAME_RECENT_COLLECTION_DURATION.get(name),
1025            INFO_MEMORY_USAGE_DESC_RECENT_COLLECTION_DURATION.get(name),
1026            recentCollectionDurationPerGC.get(name));
1027      }
1028    }
1029
1030    if (! memoryPools.isEmpty())
1031    {
1032      addMonitorAttribute(attrs,
1033           "memoryPools",
1034           INFO_MEMORY_USAGE_DISPNAME_MEMORY_POOLS.get(),
1035           INFO_MEMORY_USAGE_DESC_MEMORY_POOLS.get(),
1036           memoryPools);
1037    }
1038
1039    if (! currentBytesUsedPerMP.isEmpty())
1040    {
1041      for (final String name : currentBytesUsedPerMP.keySet())
1042      {
1043        addMonitorAttribute(attrs,
1044            "currentBytesUsed-" + name,
1045            INFO_MEMORY_USAGE_DISPNAME_CURRENT_BYTES_USED.get(name),
1046            INFO_MEMORY_USAGE_DESC_CURRENT_BYTES_USED.get(name),
1047            currentBytesUsedPerMP.get(name));
1048      }
1049    }
1050
1051    if (! bytesUsedAfterLastCollectionPerMP.isEmpty())
1052    {
1053      for (final String name : bytesUsedAfterLastCollectionPerMP.keySet())
1054      {
1055        addMonitorAttribute(attrs,
1056            "bytesUsedAfterLastCollection-" + name,
1057            INFO_MEMORY_USAGE_DISPNAME_BYTES_USED_AFTER_COLLECTION.get(name),
1058            INFO_MEMORY_USAGE_DESC_BYTES_USED_AFTER_COLLECTION.get(name),
1059            bytesUsedAfterLastCollectionPerMP.get(name));
1060      }
1061    }
1062
1063    if (nonHeapMemoryUsed != null)
1064    {
1065      addMonitorAttribute(attrs,
1066           ATTR_NON_HEAP_USED,
1067           INFO_MEMORY_USAGE_DISPNAME_NON_HEAP_MEMORY.get(),
1068           INFO_MEMORY_USAGE_DESC_NON_HEAP_MEMORY.get(),
1069           nonHeapMemoryUsed);
1070    }
1071
1072    if (totalBytesHeldByConsumers != null)
1073    {
1074      addMonitorAttribute(attrs,
1075           ATTR_TOTAL_CONSUMER_MEMORY,
1076           INFO_MEMORY_USAGE_DISPNAME_TOTAL_CONSUMER_MEMORY.get(),
1077           INFO_MEMORY_USAGE_DESC_TOTAL_CONSUMER_MEMORY.get(),
1078           totalBytesHeldByConsumers);
1079    }
1080
1081    if (percentOfMaxTenuredMemory != null)
1082    {
1083      addMonitorAttribute(attrs,
1084           ATTR_TOTAL_CONSUMER_MEMORY_AS_PCT_OF_MAX,
1085           INFO_MEMORY_USAGE_DISPNAME_CONSUMERS_AS_PCT_OF_MAX.get(),
1086           INFO_MEMORY_USAGE_DESC_CONSUMERS_AS_PCT_OF_MAX.get(),
1087           percentOfMaxTenuredMemory);
1088    }
1089
1090    if (percentOfCommittedTenuredMemory != null)
1091    {
1092      addMonitorAttribute(attrs,
1093           ATTR_TOTAL_CONSUMER_MEMORY_AS_PCT_OF_COMMITTED,
1094           INFO_MEMORY_USAGE_DISPNAME_CONSUMERS_AS_PCT_OF_COMMITTED.get(),
1095           INFO_MEMORY_USAGE_DESC_CONSUMERS_AS_PCT_OF_COMMITTED.get(),
1096           percentOfCommittedTenuredMemory);
1097    }
1098
1099    if (! detectedPauses.isEmpty())
1100    {
1101      final ArrayList<String> values =
1102           new ArrayList<String>(detectedPauses.size());
1103      for (final Map.Entry<Long,Long> e : detectedPauses.entrySet())
1104      {
1105        values.add(e.getKey() + "ms=" + e.getValue());
1106      }
1107
1108      addMonitorAttribute(attrs,
1109           PROPERTY_DETECTED_PAUSE_COUNTS,
1110           INFO_MEMORY_USAGE_DISPNAME_DETECTED_PAUSES.get(),
1111           INFO_MEMORY_USAGE_DESC_DETECTED_PAUSES.get(),
1112           values);
1113    }
1114
1115    if (maxDetectedPauseTime != null)
1116    {
1117      addMonitorAttribute(attrs,
1118           ATTR_LONGEST_PAUSE_TIME,
1119           INFO_MEMORY_USAGE_DISPNAME_MAX_PAUSE_TIME.get(),
1120           INFO_MEMORY_USAGE_DESC_MAX_PAUSE_TIME.get(),
1121           maxDetectedPauseTime);
1122    }
1123
1124    return Collections.unmodifiableMap(attrs);
1125  }
1126}