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