1 /*
  2  * Copyright (c) 2015, 2024, 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.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 package com.sun.management.internal;
 26 
 27 import com.sun.management.DiagnosticCommandMBean;
 28 import com.sun.management.HotSpotDiagnosticMXBean;
 29 import com.sun.management.ThreadMXBean;
 30 import java.lang.management.ManagementFactory;
 31 import java.lang.management.MemoryManagerMXBean;
 32 import java.lang.management.OperatingSystemMXBean;
 33 import java.util.ArrayList;
 34 import java.util.Collections;
 35 import java.util.HashMap;
 36 import java.util.List;
 37 import java.util.Map;
 38 import java.util.Set;
 39 import java.util.stream.Collectors;
 40 import java.util.stream.Stream;
 41 import javax.management.DynamicMBean;
 42 import jdk.management.VirtualThreadSchedulerMXBean;
 43 import sun.management.ManagementFactoryHelper;
 44 import sun.management.spi.PlatformMBeanProvider;
 45 
 46 @SuppressWarnings({"removal", "restricted"})
 47 public final class PlatformMBeanProviderImpl extends PlatformMBeanProvider {
 48     static final String DIAGNOSTIC_COMMAND_MBEAN_NAME =
 49         "com.sun.management:type=DiagnosticCommand";
 50 
 51     private final List<PlatformComponent<?>> mxbeanList;
 52     private static HotSpotDiagnostic hsDiagMBean = null;
 53     private static OperatingSystemMXBean osMBean = null;
 54 
 55     static {
 56        System.loadLibrary("management_ext");
 57     }
 58 
 59     public PlatformMBeanProviderImpl() {
 60         mxbeanList = Collections.unmodifiableList(init());
 61     }
 62 
 63     @Override
 64     public List<PlatformComponent<?>> getPlatformComponentList() {
 65         return mxbeanList;
 66     }
 67 
 68     private List<PlatformComponent<?>> init() {
 69         ArrayList<PlatformComponent<?>> initMBeanList = new ArrayList<>();
 70         /**
 71          * Garbage Collector in the Java virtual machine.
 72          */
 73         initMBeanList.add(new PlatformComponent<MemoryManagerMXBean>() {
 74             private final Set<String> garbageCollectorMXBeanInterfaceNames
 75                     = Collections.unmodifiableSet(
 76                             Stream.of("java.lang.management.MemoryManagerMXBean",
 77                                     "java.lang.management.GarbageCollectorMXBean",
 78                                     "com.sun.management.GarbageCollectorMXBean")
 79                             .collect(Collectors.toSet()));
 80 
 81             @Override
 82             public Set<Class<? extends MemoryManagerMXBean>> mbeanInterfaces() {
 83                 return Stream.of(MemoryManagerMXBean.class,
 84                         java.lang.management.GarbageCollectorMXBean.class,
 85                         com.sun.management.GarbageCollectorMXBean.class)
 86                         .collect(Collectors.toSet());
 87             }
 88 
 89             @Override
 90             public Set<String> mbeanInterfaceNames() {
 91                 return garbageCollectorMXBeanInterfaceNames;
 92             }
 93 
 94             @Override
 95             public String getObjectNamePattern() {
 96                 return ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",name=*";
 97             }
 98 
 99             @Override
100             public boolean isSingleton() {
101                 return false; // zero or more instances
102             }
103 
104             @Override
105             public Map<String, MemoryManagerMXBean> nameToMBeanMap() {
106                 List<java.lang.management.GarbageCollectorMXBean> list
107                         = ManagementFactoryHelper.getGarbageCollectorMXBeans();
108                 Map<String, MemoryManagerMXBean> map;
109                 if (list.isEmpty()) {
110                     map = Collections.emptyMap();
111                 } else {
112                     map = new HashMap<>(list.size());
113                     for (MemoryManagerMXBean gcm : list) {
114                         map.put(gcm.getObjectName().getCanonicalName(),
115                                 gcm);
116                     }
117                 }
118 
119                 return map;
120             }
121         });
122 
123         /**
124          * Threading system of the Java virtual machine.
125          */
126         initMBeanList.add(new PlatformComponent<java.lang.management.ThreadMXBean>() {
127             private final Set<String> threadMXBeanInterfaceNames
128                     = Collections.unmodifiableSet(
129                             Stream.of("java.lang.management.ThreadMXBean",
130                                     "com.sun.management.ThreadMXBean")
131                             .collect(Collectors.toSet()));
132             private ThreadMXBean threadMBean = null;
133 
134             @Override
135             public Set<Class<? extends java.lang.management.ThreadMXBean>> mbeanInterfaces() {
136                 return Stream.of(java.lang.management.ThreadMXBean.class,
137                         com.sun.management.ThreadMXBean.class)
138                         .collect(Collectors.toSet());
139             }
140 
141             @Override
142             public Set<String> mbeanInterfaceNames() {
143                 return threadMXBeanInterfaceNames;
144             }
145 
146             @Override
147             public String getObjectNamePattern() {
148                 return ManagementFactory.THREAD_MXBEAN_NAME;
149             }
150 
151             @Override
152             public synchronized Map<String, java.lang.management.ThreadMXBean> nameToMBeanMap() {
153                 if (threadMBean == null) {
154                     threadMBean = new HotSpotThreadImpl(ManagementFactoryHelper.getVMManagement());
155                 }
156                 return Collections.singletonMap(
157                         ManagementFactory.THREAD_MXBEAN_NAME,
158                         threadMBean);
159             }
160         });
161 
162         /**
163          * VirtualThreadSchedulerMXBean registered when using JDK's virtual thread scheduler.
164          */
165         String value = System.getProperty("jdk.virtualThreadScheduler.implClass");
166         if (value == null) {
167             initMBeanList.add(new PlatformComponent<VirtualThreadSchedulerMXBean>() {
168                 private final Set<Class<? extends VirtualThreadSchedulerMXBean>> mbeanInterfaces =
169                         Set.of(VirtualThreadSchedulerMXBean.class);
170                 private final Set<String> mbeanInterfaceNames =
171                         Set.of(VirtualThreadSchedulerMXBean.class.getName());
172                 private VirtualThreadSchedulerMXBean impl;
173 
174                 @Override
175                 public Set<Class<? extends VirtualThreadSchedulerMXBean>> mbeanInterfaces() {
176                     return mbeanInterfaces;
177                 }
178 
179                 @Override
180                 public Set<String> mbeanInterfaceNames() {
181                     return mbeanInterfaceNames;
182                 }
183 
184                 @Override
185                 public String getObjectNamePattern() {
186                     return "jdk.management:type=VirtualThreadScheduler";
187                 }
188 
189                 @Override
190                 public Map<String, VirtualThreadSchedulerMXBean> nameToMBeanMap() {
191                     VirtualThreadSchedulerMXBean impl = this.impl;
192                     if (impl == null) {
193                         this.impl = impl = VirtualThreadSchedulerImpls.create();
194                     }
195                     return Map.of("jdk.management:type=VirtualThreadScheduler", impl);
196                 }
197             });
198         }
199 
200         /**
201          * OperatingSystemMXBean
202          */
203         initMBeanList.add(new PlatformComponent<OperatingSystemMXBean>() {
204             private final Set<String> operatingSystemMXBeanInterfaceNames
205                     = Collections.unmodifiableSet(
206                             Stream.of("java.lang.management.OperatingSystemMXBean",
207                                     "com.sun.management.OperatingSystemMXBean",
208                                     "com.sun.management.UnixOperatingSystemMXBean")
209                             .collect(Collectors.toSet()));
210 
211             @Override
212             public Set<Class<? extends OperatingSystemMXBean>> mbeanInterfaces() {
213                 return Stream.of(java.lang.management.OperatingSystemMXBean.class,
214                         com.sun.management.OperatingSystemMXBean.class,
215                         com.sun.management.UnixOperatingSystemMXBean.class)
216                         .collect(Collectors.toSet());
217             }
218 
219             @Override
220             public Set<String> mbeanInterfaceNames() {
221                 return operatingSystemMXBeanInterfaceNames;
222             }
223 
224             @Override
225             public String getObjectNamePattern() {
226                 return ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME;
227             }
228 
229             @Override
230             public Map<String, java.lang.management.OperatingSystemMXBean> nameToMBeanMap() {
231                 return Collections.<String, java.lang.management.OperatingSystemMXBean>singletonMap(
232                         ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME,
233                         getOperatingSystemMXBean());
234             }
235         });
236 
237         /**
238          * Diagnostic support for the HotSpot Virtual Machine.
239          */
240         initMBeanList.add(new PlatformComponent<com.sun.management.HotSpotDiagnosticMXBean>() {
241             private final Set<String> hotSpotDiagnosticMXBeanInterfaceNames =
242                     Collections.singleton("com.sun.management.HotSpotDiagnosticMXBean");
243 
244             @Override
245             public Set<Class<? extends com.sun.management.HotSpotDiagnosticMXBean>> mbeanInterfaces() {
246                 return Collections.singleton(com.sun.management.HotSpotDiagnosticMXBean.class);
247             }
248 
249             @Override
250             public Set<String> mbeanInterfaceNames() {
251                 return hotSpotDiagnosticMXBeanInterfaceNames;
252             }
253 
254             @Override
255             public String getObjectNamePattern() {
256                 return "com.sun.management:type=HotSpotDiagnostic";
257             }
258 
259             @Override
260             public Map<String, com.sun.management.HotSpotDiagnosticMXBean> nameToMBeanMap() {
261                 return Collections.<String, com.sun.management.HotSpotDiagnosticMXBean>singletonMap(
262                         "com.sun.management:type=HotSpotDiagnostic",
263                         getDiagnosticMXBean());
264             }
265         });
266 
267         /**
268          * Diagnostic command MBean
269          */
270         DiagnosticCommandMBean diagMBean = DiagnosticCommandImpl.getDiagnosticCommandMBean();
271         if (diagMBean != null) {
272             initMBeanList.add(new PlatformComponent<DynamicMBean>() {
273                 final Set<String> dynamicMBeanInterfaceNames
274                         = Collections.singleton("javax.management.DynamicMBean");
275 
276                 @Override
277                 public Set<String> mbeanInterfaceNames() {
278                     return dynamicMBeanInterfaceNames;
279                 }
280 
281                 @Override
282                 public Set<Class<? extends DynamicMBean>> mbeanInterfaces() {
283                     // DynamicMBean cannot be used to find an MBean by ManagementFactory
284                     return Collections.emptySet();
285                 }
286 
287                 @Override
288                 public String getObjectNamePattern() {
289                     return DIAGNOSTIC_COMMAND_MBEAN_NAME;
290                 }
291 
292                 @Override
293                 public Map<String, DynamicMBean> nameToMBeanMap() {
294                     return Collections.<String, DynamicMBean>singletonMap(
295                             DIAGNOSTIC_COMMAND_MBEAN_NAME,
296                             diagMBean);
297                 }
298             });
299         }
300 
301         initMBeanList.trimToSize();
302         return initMBeanList;
303     }
304 
305     private static synchronized HotSpotDiagnosticMXBean getDiagnosticMXBean() {
306         if (hsDiagMBean == null) {
307             hsDiagMBean = new HotSpotDiagnostic();
308         }
309         return hsDiagMBean;
310     }
311 
312     private static synchronized OperatingSystemMXBean getOperatingSystemMXBean() {
313         if (osMBean == null) {
314             osMBean = new OperatingSystemImpl(ManagementFactoryHelper.getVMManagement());
315         }
316         return osMBean;
317     }
318 }