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.AOTCacheMXBean;
 43 import jdk.management.VirtualThreadSchedulerMXBean;
 44 import sun.management.ManagementFactoryHelper;
 45 import sun.management.spi.PlatformMBeanProvider;
 46 
 47 @SuppressWarnings({"removal", "restricted"})
 48 public final class PlatformMBeanProviderImpl extends PlatformMBeanProvider {
 49     static final String DIAGNOSTIC_COMMAND_MBEAN_NAME =
 50         "com.sun.management:type=DiagnosticCommand";
 51 
 52     private final List<PlatformComponent<?>> mxbeanList;
 53     private static HotSpotDiagnostic hsDiagMBean = null;
 54     private static OperatingSystemMXBean osMBean = null;
 55 
 56     static {
 57        System.loadLibrary("management_ext");
 58     }
 59 
 60     public PlatformMBeanProviderImpl() {
 61         mxbeanList = Collections.unmodifiableList(init());
 62     }
 63 
 64     @Override
 65     public List<PlatformComponent<?>> getPlatformComponentList() {
 66         return mxbeanList;
 67     }
 68 
 69     private List<PlatformComponent<?>> init() {
 70         ArrayList<PlatformComponent<?>> initMBeanList = new ArrayList<>();
 71         /**
 72          * Garbage Collector in the Java virtual machine.
 73          */
 74         initMBeanList.add(new PlatformComponent<MemoryManagerMXBean>() {
 75             private final Set<String> garbageCollectorMXBeanInterfaceNames
 76                     = Collections.unmodifiableSet(
 77                             Stream.of("java.lang.management.MemoryManagerMXBean",
 78                                     "java.lang.management.GarbageCollectorMXBean",
 79                                     "com.sun.management.GarbageCollectorMXBean")
 80                             .collect(Collectors.toSet()));
 81 
 82             @Override
 83             public Set<Class<? extends MemoryManagerMXBean>> mbeanInterfaces() {
 84                 return Stream.of(MemoryManagerMXBean.class,
 85                         java.lang.management.GarbageCollectorMXBean.class,
 86                         com.sun.management.GarbageCollectorMXBean.class)
 87                         .collect(Collectors.toSet());
 88             }
 89 
 90             @Override
 91             public Set<String> mbeanInterfaceNames() {
 92                 return garbageCollectorMXBeanInterfaceNames;
 93             }
 94 
 95             @Override
 96             public String getObjectNamePattern() {
 97                 return ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",name=*";
 98             }
 99 
100             @Override
101             public boolean isSingleton() {
102                 return false; // zero or more instances
103             }
104 
105             @Override
106             public Map<String, MemoryManagerMXBean> nameToMBeanMap() {
107                 List<java.lang.management.GarbageCollectorMXBean> list
108                         = ManagementFactoryHelper.getGarbageCollectorMXBeans();
109                 Map<String, MemoryManagerMXBean> map;
110                 if (list.isEmpty()) {
111                     map = Collections.emptyMap();
112                 } else {
113                     map = new HashMap<>(list.size());
114                     for (MemoryManagerMXBean gcm : list) {
115                         map.put(gcm.getObjectName().getCanonicalName(),
116                                 gcm);
117                     }
118                 }
119 
120                 return map;
121             }
122         });
123 
124         /**
125          * Threading system of the Java virtual machine.
126          */
127         initMBeanList.add(new PlatformComponent<java.lang.management.ThreadMXBean>() {
128             private final Set<String> threadMXBeanInterfaceNames
129                     = Collections.unmodifiableSet(
130                             Stream.of("java.lang.management.ThreadMXBean",
131                                     "com.sun.management.ThreadMXBean")
132                             .collect(Collectors.toSet()));
133             private ThreadMXBean threadMBean = null;
134 
135             @Override
136             public Set<Class<? extends java.lang.management.ThreadMXBean>> mbeanInterfaces() {
137                 return Stream.of(java.lang.management.ThreadMXBean.class,
138                         com.sun.management.ThreadMXBean.class)
139                         .collect(Collectors.toSet());
140             }
141 
142             @Override
143             public Set<String> mbeanInterfaceNames() {
144                 return threadMXBeanInterfaceNames;
145             }
146 
147             @Override
148             public String getObjectNamePattern() {
149                 return ManagementFactory.THREAD_MXBEAN_NAME;
150             }
151 
152             @Override
153             public synchronized Map<String, java.lang.management.ThreadMXBean> nameToMBeanMap() {
154                 if (threadMBean == null) {
155                     threadMBean = new HotSpotThreadImpl(ManagementFactoryHelper.getVMManagement());
156                 }
157                 return Collections.singletonMap(
158                         ManagementFactory.THREAD_MXBEAN_NAME,
159                         threadMBean);
160             }
161         });
162 
163         /**
164         * AOTCacheMXBean.
165         */
166         initMBeanList.add(new PlatformComponent<AOTCacheMXBean>() {
167             private final Set<Class<? extends AOTCacheMXBean>> mbeanInterfaces =
168                     Set.of(AOTCacheMXBean.class);
169             private final Set<String> mbeanInterfaceNames =
170                     Set.of(AOTCacheMXBean.class.getName());
171             private AOTCacheMXBean impl;
172 
173             @Override
174             public Set<Class<? extends AOTCacheMXBean>> mbeanInterfaces() {
175                 return mbeanInterfaces;
176             }
177 
178             @Override
179             public Set<String> mbeanInterfaceNames() {
180                 return mbeanInterfaceNames;
181             }
182 
183             @Override
184             public String getObjectNamePattern() {
185                 return "jdk.management:type=AOTCache";
186             }
187 
188             @Override
189             public Map<String, AOTCacheMXBean> nameToMBeanMap() {
190                 AOTCacheMXBean impl = this.impl;
191                 if (impl == null) {
192                     this.impl = impl = new AOTCacheImpl(ManagementFactoryHelper.getVMManagement());
193                 }
194                 return Map.of("jdk.management:type=AOTCache", impl);
195             }
196         });
197 
198         /**
199          * VirtualThreadSchedulerMXBean.
200          */
201         initMBeanList.add(new PlatformComponent<VirtualThreadSchedulerMXBean>() {
202             private final Set<Class<? extends VirtualThreadSchedulerMXBean>> mbeanInterfaces =
203                     Set.of(VirtualThreadSchedulerMXBean.class);
204             private final Set<String> mbeanInterfaceNames =
205                     Set.of(VirtualThreadSchedulerMXBean.class.getName());
206             private VirtualThreadSchedulerMXBean impl;
207 
208             @Override
209             public Set<Class<? extends VirtualThreadSchedulerMXBean>> mbeanInterfaces() {
210                 return mbeanInterfaces;
211             }
212 
213             @Override
214             public Set<String> mbeanInterfaceNames() {
215                 return mbeanInterfaceNames;
216             }
217 
218             @Override
219             public String getObjectNamePattern() {
220                 return "jdk.management:type=VirtualThreadScheduler";
221             }
222 
223             @Override
224             public Map<String, VirtualThreadSchedulerMXBean> nameToMBeanMap() {
225                 VirtualThreadSchedulerMXBean impl = this.impl;
226                 if (impl == null) {
227                     this.impl = impl = VirtualThreadSchedulerImpls.create();
228                 }
229                 return Map.of("jdk.management:type=VirtualThreadScheduler", impl);
230             }
231         });
232 
233         /**
234          * OperatingSystemMXBean
235          */
236         initMBeanList.add(new PlatformComponent<OperatingSystemMXBean>() {
237             private final Set<String> operatingSystemMXBeanInterfaceNames
238                     = Collections.unmodifiableSet(
239                             Stream.of("java.lang.management.OperatingSystemMXBean",
240                                     "com.sun.management.OperatingSystemMXBean",
241                                     "com.sun.management.UnixOperatingSystemMXBean")
242                             .collect(Collectors.toSet()));
243 
244             @Override
245             public Set<Class<? extends OperatingSystemMXBean>> mbeanInterfaces() {
246                 return Stream.of(java.lang.management.OperatingSystemMXBean.class,
247                         com.sun.management.OperatingSystemMXBean.class,
248                         com.sun.management.UnixOperatingSystemMXBean.class)
249                         .collect(Collectors.toSet());
250             }
251 
252             @Override
253             public Set<String> mbeanInterfaceNames() {
254                 return operatingSystemMXBeanInterfaceNames;
255             }
256 
257             @Override
258             public String getObjectNamePattern() {
259                 return ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME;
260             }
261 
262             @Override
263             public Map<String, java.lang.management.OperatingSystemMXBean> nameToMBeanMap() {
264                 return Collections.<String, java.lang.management.OperatingSystemMXBean>singletonMap(
265                         ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME,
266                         getOperatingSystemMXBean());
267             }
268         });
269 
270         /**
271          * Diagnostic support for the HotSpot Virtual Machine.
272          */
273         initMBeanList.add(new PlatformComponent<com.sun.management.HotSpotDiagnosticMXBean>() {
274             private final Set<String> hotSpotDiagnosticMXBeanInterfaceNames =
275                     Collections.singleton("com.sun.management.HotSpotDiagnosticMXBean");
276 
277             @Override
278             public Set<Class<? extends com.sun.management.HotSpotDiagnosticMXBean>> mbeanInterfaces() {
279                 return Collections.singleton(com.sun.management.HotSpotDiagnosticMXBean.class);
280             }
281 
282             @Override
283             public Set<String> mbeanInterfaceNames() {
284                 return hotSpotDiagnosticMXBeanInterfaceNames;
285             }
286 
287             @Override
288             public String getObjectNamePattern() {
289                 return "com.sun.management:type=HotSpotDiagnostic";
290             }
291 
292             @Override
293             public Map<String, com.sun.management.HotSpotDiagnosticMXBean> nameToMBeanMap() {
294                 return Collections.<String, com.sun.management.HotSpotDiagnosticMXBean>singletonMap(
295                         "com.sun.management:type=HotSpotDiagnostic",
296                         getDiagnosticMXBean());
297             }
298         });
299 
300         /**
301          * Diagnostic command MBean
302          */
303         DiagnosticCommandMBean diagMBean = DiagnosticCommandImpl.getDiagnosticCommandMBean();
304         if (diagMBean != null) {
305             initMBeanList.add(new PlatformComponent<DynamicMBean>() {
306                 final Set<String> dynamicMBeanInterfaceNames
307                         = Collections.singleton("javax.management.DynamicMBean");
308 
309                 @Override
310                 public Set<String> mbeanInterfaceNames() {
311                     return dynamicMBeanInterfaceNames;
312                 }
313 
314                 @Override
315                 public Set<Class<? extends DynamicMBean>> mbeanInterfaces() {
316                     // DynamicMBean cannot be used to find an MBean by ManagementFactory
317                     return Collections.emptySet();
318                 }
319 
320                 @Override
321                 public String getObjectNamePattern() {
322                     return DIAGNOSTIC_COMMAND_MBEAN_NAME;
323                 }
324 
325                 @Override
326                 public Map<String, DynamicMBean> nameToMBeanMap() {
327                     return Collections.<String, DynamicMBean>singletonMap(
328                             DIAGNOSTIC_COMMAND_MBEAN_NAME,
329                             diagMBean);
330                 }
331             });
332         }
333 
334         initMBeanList.trimToSize();
335         return initMBeanList;
336     }
337 
338     private static synchronized HotSpotDiagnosticMXBean getDiagnosticMXBean() {
339         if (hsDiagMBean == null) {
340             hsDiagMBean = new HotSpotDiagnostic();
341         }
342         return hsDiagMBean;
343     }
344 
345     private static synchronized OperatingSystemMXBean getOperatingSystemMXBean() {
346         if (osMBean == null) {
347             osMBean = new OperatingSystemImpl(ManagementFactoryHelper.getVMManagement());
348         }
349         return osMBean;
350     }
351 }