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