001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.lang.management;
019:
020: import java.io.IOException;
021: import java.lang.reflect.Proxy;
022: import java.security.AccessController;
023: import java.security.PrivilegedAction;
024: import java.util.HashMap;
025: import java.util.HashSet;
026: import java.util.Iterator;
027: import java.util.List;
028: import java.util.Map;
029: import java.util.Set;
030: import java.util.logging.LogManager;
031:
032: import javax.management.InstanceAlreadyExistsException;
033: import javax.management.MBeanRegistrationException;
034: import javax.management.MBeanServer;
035: import javax.management.MBeanServerConnection;
036: import javax.management.MBeanServerFactory;
037: import javax.management.MBeanServerPermission;
038: import javax.management.MalformedObjectNameException;
039: import javax.management.NotCompliantMBeanException;
040: import javax.management.NotificationEmitter;
041: import javax.management.ObjectName;
042:
043: import org.apache.harmony.lang.management.ManagementUtils;
044: import org.apache.harmony.lang.management.MemoryManagerMXBeanImpl;
045: import org.apache.harmony.lang.management.OpenTypeMappingIHandler;
046:
047: /**
048: * <p>
049: * The factory for retrieving all managed object for the JVM as well as the
050: * JVM's MBean server.
051: * </p>
052: *
053: * @since 1.5
054: */
055: public class ManagementFactory {
056: /**
057: * <p>
058: * The String value of the {@link ObjectName} for {@link ClassLoadingMXBean}.
059: * </p>
060: */
061: public static final String CLASS_LOADING_MXBEAN_NAME = "java.lang:type=ClassLoading";
062:
063: /**
064: * <p>
065: * The String value of the {@link ObjectName} for {@link CompilationMXBean}.
066: * </p>
067: */
068: public static final String COMPILATION_MXBEAN_NAME = "java.lang:type=Compilation";
069:
070: /**
071: * <p>
072: * The String value of the {@link ObjectName} for
073: * {@link GarbageCollectorMXBean}.
074: * </p>
075: */
076: public static final String GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE = "java.lang:type=GarbageCollector";
077:
078: /**
079: * <p>
080: * The String value of the {@link ObjectName} for
081: * {@link MemoryManagerMXBean}.
082: * </p>
083: */
084: public static final String MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE = "java.lang:type=MemoryManager";
085:
086: /**
087: * <p>
088: * The String value of the {@link ObjectName} for {@link MemoryMXBean}.
089: * </p>
090: */
091: public static final String MEMORY_MXBEAN_NAME = "java.lang:type=Memory";
092:
093: /**
094: * <p>
095: * The String value of the {@link ObjectName} for {@link MemoryPoolMXBean}.
096: * </p>
097: */
098: public static final String MEMORY_POOL_MXBEAN_DOMAIN_TYPE = "java.lang:type=MemoryPool";
099:
100: /**
101: * <p>
102: * The String value of the {@link ObjectName} for
103: * {@link OperatingSystemMXBean}.
104: * </p>
105: */
106: public static final String OPERATING_SYSTEM_MXBEAN_NAME = "java.lang:type=OperatingSystem";
107:
108: /**
109: * <p>
110: * The String value of the {@link ObjectName} for {@link RuntimeMXBean}.
111: * </p>
112: */
113: public static final String RUNTIME_MXBEAN_NAME = "java.lang:type=Runtime";
114:
115: /**
116: * <p>
117: * The String value of the {@link ObjectName} for {@link ThreadMXBean}.
118: * </p>
119: */
120: public static final String THREAD_MXBEAN_NAME = "java.lang:type=Threading";
121:
122: /**
123: * Reference to the MBean server. In addition to playing the role of an
124: * MBean registry, the MBean server also provides a way for management
125: * systems to find and utilise registered MBeans.
126: */
127: private static MBeanServer platformServer;
128:
129: private static Map<String, String> interfaceNameLookupTable;
130:
131: private static Set<String> multiInstanceBeanNames;
132:
133: static {
134: interfaceNameLookupTable = new HashMap<String, String>();
135: // Public API types
136: interfaceNameLookupTable.put(
137: "java.lang.management.ClassLoadingMXBean",
138: CLASS_LOADING_MXBEAN_NAME);
139: interfaceNameLookupTable
140: .put("java.lang.management.MemoryMXBean",
141: MEMORY_MXBEAN_NAME);
142: interfaceNameLookupTable
143: .put("java.lang.management.ThreadMXBean",
144: THREAD_MXBEAN_NAME);
145: interfaceNameLookupTable.put(
146: "java.lang.management.RuntimeMXBean",
147: RUNTIME_MXBEAN_NAME);
148: interfaceNameLookupTable.put(
149: "java.lang.management.OperatingSystemMXBean",
150: OPERATING_SYSTEM_MXBEAN_NAME);
151: interfaceNameLookupTable.put(
152: "java.lang.management.CompilationMXBean",
153: COMPILATION_MXBEAN_NAME);
154: interfaceNameLookupTable.put(
155: "java.lang.management.GarbageCollectorMXBean",
156: GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE);
157: interfaceNameLookupTable.put(
158: "java.lang.management.MemoryManagerMXBean",
159: MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE);
160: interfaceNameLookupTable.put(
161: "java.lang.management.MemoryPoolMXBean",
162: MEMORY_POOL_MXBEAN_DOMAIN_TYPE);
163:
164: multiInstanceBeanNames = new HashSet<String>();
165: multiInstanceBeanNames
166: .add("java.lang.management.GarbageCollectorMXBean");
167: multiInstanceBeanNames
168: .add("java.lang.management.MemoryManagerMXBean");
169: multiInstanceBeanNames
170: .add("java.lang.management.MemoryPoolMXBean");
171: }
172:
173: /**
174: * Private constructor ensures that this class cannot be instantiated by
175: * users.
176: */
177: private ManagementFactory() {
178: // NO OP
179: }
180:
181: /**
182: * Returns the singleton <code>MXBean</code> for the virtual machine's
183: * class loading system.
184: *
185: * @return the virtual machine's {@link ClassLoadingMXBean}
186: */
187: public static ClassLoadingMXBean getClassLoadingMXBean() {
188: return ManagementUtils.getClassLoadingBean();
189: }
190:
191: /**
192: * Returns the singleton <code>MXBean</code> for the virtual machine's
193: * compilation system <i>if and only if the virtual machine has a
194: * compilation system enabled </i>. If no compilation exists for this
195: * virtual machine, a <code>null</code> is returned.
196: *
197: * @return the virtual machine's {@link CompilationMXBean}or
198: * <code>null</code> if there is no compilation system for this
199: * virtual machine.
200: */
201: public static CompilationMXBean getCompilationMXBean() {
202: return ManagementUtils.getCompliationBean();
203: }
204:
205: /**
206: * Returns a list of all of the instances of {@link GarbageCollectorMXBean}
207: * in this virtual machine. Owing to the dynamic nature of this kind of
208: * <code>MXBean</code>, it is possible that instances may be created or
209: * destroyed between the invocation and return of this method.
210: *
211: * @return a list of all known <code>GarbageCollectorMXBean</code> s in
212: * this virtual machine.
213: */
214: public static List<GarbageCollectorMXBean> getGarbageCollectorMXBeans() {
215: return ManagementUtils.getGarbageCollectorMXBeans();
216: }
217:
218: /**
219: * Returns a list of all of the instances of {@link MemoryManagerMXBean}in
220: * this virtual machine. Owing to the dynamic nature of this kind of
221: * <code>MXBean</code>, it is possible that instances may be created or
222: * destroyed between the invocation and return of this method.
223: * <p>
224: * Note that the list of <code>MemoryManagerMXBean</code> instances will
225: * include instances of <code>MemoryManagerMXBean</code> sub-types such as
226: * <code>GarbageCollectorMXBean</code>.
227: * </p>
228: *
229: * @return a list of all known <code>MemoryManagerMXBean</code> s in this
230: * virtual machine.
231: */
232: public static List<MemoryManagerMXBean> getMemoryManagerMXBeans() {
233: return ManagementUtils.getMemoryManagerMXBeans();
234: }
235:
236: /**
237: * Returns the singleton <code>MXBean</code> for the virtual machine's
238: * memory system.
239: *
240: * @return the virtual machine's {@link MemoryMXBean}
241: */
242: public static MemoryMXBean getMemoryMXBean() {
243: return ManagementUtils.getMemoryBean();
244: }
245:
246: /**
247: * Returns a list of all of the instances of {@link MemoryPoolMXBean}in
248: * this virtual machine. Owing to the dynamic nature of this kind of
249: * <code>MXBean</code>, it is possible that instances may be created or
250: * destroyed between the invocation and return of this method.
251: *
252: * @return a list of all known <code>MemoryPoolMXBean</code> s in this
253: * virtual machine.
254: */
255: public static List<MemoryPoolMXBean> getMemoryPoolMXBeans() {
256: return ManagementUtils.getMemoryPoolMXBeans();
257: }
258:
259: /**
260: * Returns the singleton <code>MXBean</code> for the operating system
261: * which the virtual machine runs on.
262: *
263: * @return the virtual machine's {@link OperatingSystemMXBean}
264: */
265: public static OperatingSystemMXBean getOperatingSystemMXBean() {
266: return ManagementUtils.getOperatingSystemBean();
267: }
268:
269: /**
270: * Returns a reference to the virtual machine's platform
271: * <code>MBeanServer</code>. This <code>MBeanServer</code> will have
272: * all of the platform <code>MXBean</code> s registered with it including
273: * any dynamic <code>MXBean</code> s (e.g. instances of
274: * {@link GarbageCollectorMXBean}that may be unregistered and destroyed at
275: * a later time.
276: * <p>
277: * In order to simplify the process of distribution and discovery of managed
278: * beans it is good practice to register all managed beans (in addition to
279: * the platform <code>MXBean</code>s) with this server.
280: * </p>
281: * <p>
282: * A custom <code>MBeanServer</code> can be created by this method if the
283: * System property <code>javax.management.builder.initial</code> has been
284: * set with the fully qualified name of a subclass of
285: * {@link javax.management.MBeanServerBuilder}.
286: * </p>
287: *
288: * @return the platform <code>MBeanServer</code>.
289: * @throws SecurityException
290: * if there is a Java security manager in operation and the
291: * caller of this method does not have
292: * "createMBeanServer"
293: * <code>MBeanServerPermission</code>.
294: * @see MBeanServer
295: * @see javax.management.MBeanServerPermission
296: */
297: public static MBeanServer getPlatformMBeanServer() {
298: SecurityManager security = System.getSecurityManager();
299: if (security != null) {
300: security.checkPermission(new MBeanServerPermission(
301: "createMBeanServer"));
302: }
303:
304: synchronized (ManagementFactory.class) {
305: if (platformServer == null) {
306: platformServer = MBeanServerFactory.createMBeanServer();
307:
308: AccessController
309: .doPrivileged(new PrivilegedAction<Object>() {
310: public Object run() {
311: registerPlatformBeans(platformServer);
312: return null;
313: }// end method run
314: });
315: }
316: }// end synchronized
317: return platformServer;
318: }
319:
320: /**
321: * Returns the singleton <code>MXBean</code> for the virtual machine's
322: * runtime system.
323: *
324: * @return the virtual machine's {@link RuntimeMXBean}
325: */
326: public static RuntimeMXBean getRuntimeMXBean() {
327: return ManagementUtils.getRuntimeBean();
328: }
329:
330: /**
331: * Returns the singleton <code>MXBean</code> for the virtual machine's
332: * threading system.
333: *
334: * @return the virtual machine's {@link ThreadMXBean}
335: */
336: public static ThreadMXBean getThreadMXBean() {
337: return ManagementUtils.getThreadBean();
338: }
339:
340: /**
341: * @param <T>
342: * @param connection
343: * @param mxbeanName
344: * @param mxbeanInterface
345: * @return a new proxy object representing the named <code>MXBean</code>.
346: * All subsequent method invocations on the proxy will be routed
347: * through the supplied {@link MBeanServerConnection} object.
348: * @throws IOException
349: */
350: @SuppressWarnings("unchecked")
351: public static <T> T newPlatformMXBeanProxy(
352: MBeanServerConnection connection, String mxbeanName,
353: Class<T> mxbeanInterface) throws IOException {
354: // Check that the named object implements the specified interface
355: verifyNamedMXBean(mxbeanName, mxbeanInterface);
356:
357: T result = null;
358: Class[] interfaces = null;
359: if (ManagementUtils.isANotificationEmitter(mxbeanInterface)) {
360: // Proxies of the MemoryMXBean and OperatingSystemMXBean interfaces
361: // must also implement the NotificationEmitter interface.
362: interfaces = new Class[] { mxbeanInterface,
363: NotificationEmitter.class };
364: } else {
365: interfaces = new Class[] { mxbeanInterface };
366: }
367:
368: result = (T) Proxy.newProxyInstance(interfaces[0]
369: .getClassLoader(), interfaces,
370: new OpenTypeMappingIHandler(connection, mxbeanInterface
371: .getName(), mxbeanName));
372: return result;
373: }
374:
375: /**
376: * @param mxbeanName
377: * @param mxbeanInterface
378: */
379: private static void verifyNamedMXBean(String mxbeanName,
380: Class<?> mxbeanInterface) {
381: String mxbeanInterfaceName = mxbeanInterface.getName();
382: String expectedObjectName = interfaceNameLookupTable
383: .get(mxbeanInterfaceName);
384: if (multiInstanceBeanNames.contains(mxbeanInterfaceName)) {
385: // partial match is good enough
386: if (!mxbeanName.startsWith(expectedObjectName)) {
387: throw new IllegalArgumentException(mxbeanName
388: + " is not an instance of interface "
389: + mxbeanInterfaceName);
390: }
391: } else {
392: // exact match required
393: if (!expectedObjectName.equals(mxbeanName)) {
394: throw new IllegalArgumentException(mxbeanName
395: + " is not an instance of interface "
396: + mxbeanInterfaceName);
397: }
398: }
399: }
400:
401: /**
402: * Register the singleton platform MXBeans :
403: * <ul>
404: * <li>ClassLoadingMXBean
405: * <li>MemoryMXBean
406: * <li>ThreadMXBean
407: * <li>RuntimeMXBean
408: * <li>OperatingSystemMXBean
409: * <li>CompilationMXBean ( <i>only if the VM has a compilation system </i>)
410: * </ul>
411: * <p>
412: * This method will be called only once in the lifetime of the virtual
413: * machine, at the point where the singleton platform MBean server has been
414: * created.
415: *
416: * @param platformServer
417: * the platform <code>MBeanServer</code> for this virtual
418: * machine.
419: */
420: private static void registerPlatformBeans(MBeanServer platformServer) {
421: try {
422: ObjectName oName = new ObjectName(CLASS_LOADING_MXBEAN_NAME);
423: if (!platformServer.isRegistered(oName)) {
424: platformServer.registerMBean(ManagementUtils
425: .getClassLoadingBean(), oName);
426: }
427:
428: oName = new ObjectName(LogManager.LOGGING_MXBEAN_NAME);
429: if (!platformServer.isRegistered(oName)) {
430: platformServer.registerMBean(ManagementUtils
431: .getLoggingBean(), oName);
432: }
433:
434: oName = new ObjectName(MEMORY_MXBEAN_NAME);
435: if (!platformServer.isRegistered(oName)) {
436: platformServer.registerMBean(ManagementUtils
437: .getMemoryBean(), oName);
438: }
439:
440: oName = new ObjectName(THREAD_MXBEAN_NAME);
441: if (!platformServer.isRegistered(oName)) {
442: platformServer.registerMBean(ManagementUtils
443: .getThreadBean(), oName);
444: }
445:
446: oName = new ObjectName(RUNTIME_MXBEAN_NAME);
447: if (!platformServer.isRegistered(oName)) {
448: platformServer.registerMBean(ManagementUtils
449: .getRuntimeBean(), oName);
450: }
451:
452: oName = new ObjectName(OPERATING_SYSTEM_MXBEAN_NAME);
453: if (!platformServer.isRegistered(oName)) {
454: platformServer.registerMBean(ManagementUtils
455: .getOperatingSystemBean(), oName);
456: }
457:
458: // If there is no JIT compiler available, there will be no
459: // compilation MXBean.
460: CompilationMXBean cBean = ManagementUtils
461: .getCompliationBean();
462: if (cBean != null) {
463: oName = new ObjectName(COMPILATION_MXBEAN_NAME);
464: if (!platformServer.isRegistered(oName)) {
465: platformServer.registerMBean(cBean, oName);
466: }
467: }// end if compilation bean is not null
468:
469: // Carry out the initial registration of Dynamic MXBeans.
470: List<MemoryPoolMXBean> mpBeanList = ManagementUtils
471: .getMemoryPoolMXBeans();
472: if (mpBeanList != null) {
473: Iterator<MemoryPoolMXBean> mpIt = mpBeanList.iterator();
474: while (mpIt.hasNext()) {
475: MemoryPoolMXBean mpBean = mpIt.next();
476: oName = new ObjectName(
477: MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",name="
478: + mpBean.getName());
479: if (!platformServer.isRegistered(oName)) {
480: platformServer.registerMBean(mpBean, oName);
481: }
482: }// end while
483: }
484:
485: List<GarbageCollectorMXBean> gcBeanList = ManagementUtils
486: .getGarbageCollectorMXBeans();
487: if (gcBeanList != null) {
488: Iterator<GarbageCollectorMXBean> gcIt = gcBeanList
489: .iterator();
490: while (gcIt.hasNext()) {
491: GarbageCollectorMXBean gcBean = gcIt.next();
492: oName = new ObjectName(
493: GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE
494: + ",name=" + gcBean.getName());
495: if (!platformServer.isRegistered(oName)) {
496: platformServer.registerMBean(gcBean, oName);
497: }
498: }// end while
499: }
500:
501: // Careful ! The getMemoryManagerMXBeans call returns objects that
502: // are memory managers (with the MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE
503: // prefix in their object name) *and* garbage collectors (with the
504: // GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE prefix in their object
505: // name).
506: // This is because garbage collector platform beans extend
507: // memory manager platform beans and so qualify for inclusion in
508: // the list of memory manager beans.
509: List<MemoryManagerMXBean> mmBeanList = ManagementUtils
510: .getMemoryManagerMXBeans();
511: if (mmBeanList != null) {
512: Iterator<MemoryManagerMXBean> mmIt = mmBeanList
513: .iterator();
514: while (mmIt.hasNext()) {
515: MemoryManagerMXBean mmBean = mmIt.next();
516: // Test the bean's runtime class. Only register this bean
517: // if it's runtime type is MemoryManagerMXBeanImpl.
518: if (mmBean.getClass().equals(
519: MemoryManagerMXBeanImpl.class)) {
520: oName = new ObjectName(
521: MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE
522: + ",name=" + mmBean.getName());
523: if (!platformServer.isRegistered(oName)) {
524: platformServer.registerMBean(mmBean, oName);
525: }
526: }
527: }// end while
528: }
529: } catch (InstanceAlreadyExistsException e) {
530: if (ManagementUtils.VERBOSE_MODE) {
531: e.printStackTrace(System.err);
532: }// end if
533: } catch (MBeanRegistrationException e) {
534: if (ManagementUtils.VERBOSE_MODE) {
535: e.printStackTrace(System.err);
536: }// end if
537: } catch (NotCompliantMBeanException e) {
538: if (ManagementUtils.VERBOSE_MODE) {
539: e.printStackTrace(System.err);
540: }// end if
541: } catch (MalformedObjectNameException e) {
542: if (ManagementUtils.VERBOSE_MODE) {
543: e.printStackTrace(System.err);
544: }// end if
545: } catch (NullPointerException e) {
546: if (ManagementUtils.VERBOSE_MODE) {
547: e.printStackTrace(System.err);
548: }// end if
549: }
550: }
551: }
|