1 /*
   2  * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.lang.management.GarbageCollectorMXBean;
  25 import java.lang.management.ManagementFactory;
  26 import java.util.Arrays;
  27 import java.util.Objects;
  28 
  29 import com.sun.management.HotSpotDiagnosticMXBean;
  30 import com.sun.management.VMOption;
  31 
  32 /**
  33  * Helper class with enum representation of GC types.
  34  */
  35 public final class GCTypes {
  36 
  37     private static <T extends GCType> T getCurrentGCType(Class<T> type) {
  38         return ManagementFactory.getGarbageCollectorMXBeans().stream()
  39                 .map(bean -> getGCTypeByName(type, bean.getName()))
  40                 .filter(Objects::nonNull)
  41                 .findFirst()
  42                 .orElse(null);
  43     }
  44 
  45     private static <T extends GCType> T getGCTypeByName(Class<T> type, String name) {
  46         return Arrays.stream(type.getEnumConstants())
  47                 .filter(e -> e.getGCName().equals(name))
  48                 .findFirst()
  49                 .orElse(null);
  50     }
  51 
  52     private static <T extends GCType> GarbageCollectorMXBean getGCBeanByType(Class<T> type) {
  53         return ManagementFactory.getGarbageCollectorMXBeans().stream()
  54                 .filter(bean -> Arrays.stream(type.getEnumConstants())
  55                         .filter(enumName -> enumName.getGCName().equals(bean.getName()))
  56                         .findFirst()
  57                         .isPresent()
  58                 )
  59                 .findFirst()
  60                 .orElse(null);
  61     }
  62 
  63     public static class LegacyMonitoring {
  64         private static final boolean useLegacyMonitoring = getUseLegacyMonitoring();
  65 
  66         private static boolean getUseLegacyMonitoring() {
  67             HotSpotDiagnosticMXBean diagnostic
  68                 = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
  69             VMOption option = diagnostic.getVMOption("G1UseLegacyMonitoring");
  70             return option.getValue().equals("true");
  71         }
  72 
  73         public static boolean use() { return useLegacyMonitoring; }
  74     }
  75 
  76     /**
  77      * Helper interface used by GCTypes static methods
  78      * to get gcTypeName field of *GCType classes.
  79      */
  80     private interface GCType {
  81         String getGCName();
  82     }
  83 
  84     public static enum YoungGCType implements GCType {
  85         DefNew("Copy"),
  86         ParNew("ParNew"),
  87         PSNew("PS Scavenge"),
  88         G1("G1");
  89 
  90         @Override
  91         public String getGCName() {
  92             return gcTypeName;
  93         }
  94         private final String gcTypeName;
  95 
  96         private YoungGCType(String name) {
  97             if (name.contains("G1")) {
  98                 name = LegacyMonitoring.use() ? "G1 Young Generation" : "G1 Young";
  99             }
 100             gcTypeName = name;
 101         }
 102 
 103         public static YoungGCType getYoungGCType() {
 104             return GCTypes.getCurrentGCType(YoungGCType.class);
 105         }
 106 
 107         public static GarbageCollectorMXBean getYoungGCBean() {
 108             return GCTypes.getGCBeanByType(YoungGCType.class);
 109         }
 110     }
 111 
 112     public static enum OldGCType implements GCType {
 113         Serial("MarkSweepCompact"),
 114         CMS("ConcurrentMarkSweep"),
 115         PSOld("PS MarkSweep"),
 116         G1("G1");
 117 
 118         private final String gcTypeName;
 119 
 120         private OldGCType(String name) {
 121             if (name.contains("G1")) {
 122                 name = LegacyMonitoring.use() ? "G1 Old Generation" : "G1 Full";
 123             }
 124             gcTypeName = name;
 125         }
 126 
 127         public static OldGCType getOldGCType() {
 128             return GCTypes.getCurrentGCType(OldGCType.class);
 129         }
 130 
 131         @Override
 132         public String getGCName() {
 133             return gcTypeName;
 134         }
 135     }
 136 }