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.
169          */
170         initMBeanList.add(new PlatformComponent<VirtualThreadSchedulerMXBean>() {
171             private final Set<Class<? extends VirtualThreadSchedulerMXBean>> mbeanInterfaces =
172                     Set.of(VirtualThreadSchedulerMXBean.class);
173             private final Set<String> mbeanInterfaceNames =
174                     Set.of(VirtualThreadSchedulerMXBean.class.getName());
175             private VirtualThreadSchedulerMXBean impl;
176 
177             @Override
178             public Set<Class<? extends VirtualThreadSchedulerMXBean>> mbeanInterfaces() {
179                 return mbeanInterfaces;
180             }
181 
182             @Override
183             public Set<String> mbeanInterfaceNames() {
184                 return mbeanInterfaceNames;
185             }
186 
187             @Override
188             public String getObjectNamePattern() {
189                 return "jdk.management:type=VirtualThreadScheduler";
190             }
191 
192             @Override
193             public Map<String, VirtualThreadSchedulerMXBean> nameToMBeanMap() {
194                 VirtualThreadSchedulerMXBean impl = this.impl;
195                 if (impl == null) {
196                     this.impl = impl = VirtualThreadSchedulerImpls.create();
197                 }
198                 return Map.of("jdk.management:type=VirtualThreadScheduler", impl);
199             }
200         });
201 
202         /**
203          * OperatingSystemMXBean
204          */
205         initMBeanList.add(new PlatformComponent<OperatingSystemMXBean>() {
206             private final Set<String> operatingSystemMXBeanInterfaceNames
207                     = Collections.unmodifiableSet(
208                             Stream.of("java.lang.management.OperatingSystemMXBean",
209                                     "com.sun.management.OperatingSystemMXBean",
210                                     "com.sun.management.UnixOperatingSystemMXBean")
211                             .collect(Collectors.toSet()));
212 
213             @Override
214             public Set<Class<? extends OperatingSystemMXBean>> mbeanInterfaces() {
215                 return Stream.of(java.lang.management.OperatingSystemMXBean.class,
216                         com.sun.management.OperatingSystemMXBean.class,
217                         com.sun.management.UnixOperatingSystemMXBean.class)
218                         .collect(Collectors.toSet());
219             }
220 
221             @Override
222             public Set<String> mbeanInterfaceNames() {
223                 return operatingSystemMXBeanInterfaceNames;
224             }
225 
226             @Override
227             public String getObjectNamePattern() {
228                 return ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME;
229             }
230 
231             @Override
232             public Map<String, java.lang.management.OperatingSystemMXBean> nameToMBeanMap() {
233                 return Collections.<String, java.lang.management.OperatingSystemMXBean>singletonMap(
234                         ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME,
235                         getOperatingSystemMXBean());
236             }
237         });
238 
239         /**
240          * Diagnostic support for the HotSpot Virtual Machine.
241          */
242         initMBeanList.add(new PlatformComponent<com.sun.management.HotSpotDiagnosticMXBean>() {
243             private final Set<String> hotSpotDiagnosticMXBeanInterfaceNames =
244                     Collections.singleton("com.sun.management.HotSpotDiagnosticMXBean");
245 
246             @Override
247             public Set<Class<? extends com.sun.management.HotSpotDiagnosticMXBean>> mbeanInterfaces() {
248                 return Collections.singleton(com.sun.management.HotSpotDiagnosticMXBean.class);
249             }
250 
251             @Override
252             public Set<String> mbeanInterfaceNames() {
253                 return hotSpotDiagnosticMXBeanInterfaceNames;
254             }
255 
256             @Override
257             public String getObjectNamePattern() {
258                 return "com.sun.management:type=HotSpotDiagnostic";
259             }
260 
261             @Override
262             public Map<String, com.sun.management.HotSpotDiagnosticMXBean> nameToMBeanMap() {
263                 return Collections.<String, com.sun.management.HotSpotDiagnosticMXBean>singletonMap(
264                         "com.sun.management:type=HotSpotDiagnostic",
265                         getDiagnosticMXBean());
266             }
267         });
268 
269         /**
270          * Diagnostic command MBean
271          */
272         DiagnosticCommandMBean diagMBean = DiagnosticCommandImpl.getDiagnosticCommandMBean();
273         if (diagMBean != null) {
274             initMBeanList.add(new PlatformComponent<DynamicMBean>() {
275                 final Set<String> dynamicMBeanInterfaceNames
276                         = Collections.singleton("javax.management.DynamicMBean");
277 
278                 @Override
279                 public Set<String> mbeanInterfaceNames() {
280                     return dynamicMBeanInterfaceNames;
281                 }
282 
283                 @Override
284                 public Set<Class<? extends DynamicMBean>> mbeanInterfaces() {
285                     // DynamicMBean cannot be used to find an MBean by ManagementFactory
286                     return Collections.emptySet();
287                 }
288 
289                 @Override
290                 public String getObjectNamePattern() {
291                     return DIAGNOSTIC_COMMAND_MBEAN_NAME;
292                 }
293 
294                 @Override
295                 public Map<String, DynamicMBean> nameToMBeanMap() {
296                     return Collections.<String, DynamicMBean>singletonMap(
297                             DIAGNOSTIC_COMMAND_MBEAN_NAME,
298                             diagMBean);
299                 }
300             });
301         }
302 
303         initMBeanList.trimToSize();
304         return initMBeanList;
305     }
306 
307     private static synchronized HotSpotDiagnosticMXBean getDiagnosticMXBean() {
308         if (hsDiagMBean == null) {
309             hsDiagMBean = new HotSpotDiagnostic();
310         }
311         return hsDiagMBean;
312     }
313 
314     private static synchronized OperatingSystemMXBean getOperatingSystemMXBean() {
315         if (osMBean == null) {
316             osMBean = new OperatingSystemImpl(ManagementFactoryHelper.getVMManagement());
317         }
318         return osMBean;
319     }
320 }