1
18 package net.bull.javamelody.internal.model;
19
20 import java.util.Collections;
21 import java.util.HashSet;
22 import java.util.Set;
23
24 import javax.management.JMException;
25 import javax.management.MBeanAttributeInfo;
26 import javax.management.MBeanInfo;
27 import javax.management.MBeanServer;
28 import javax.management.MalformedObjectNameException;
29 import javax.management.ObjectName;
30
31
35 final class MBeansAccessor {
36 private static final MBeanServer MBEAN_SERVER = MBeans.getPlatformMBeanServer();
37 private static final Set<ObjectName> NIO_BUFFER_POOLS = getNioBufferPools();
38 private static final ObjectName OPERATING_SYSTEM = createObjectName(
39 "java.lang:type=OperatingSystem");
40 private static final Set<String> OPERATING_SYSTEM_ATTRIBUTES = getAttributesNames(
41 OPERATING_SYSTEM);
42 private static final ObjectName THREADING = createObjectName("java.lang:type=Threading");
43 private static final boolean MBEAN_ALLOCATED_BYTES_ENABLED = isMbeanAllocatedBytesEnabled();
44 private static final String[] THREAD_ALLOCATED_BYTES_SIGNATURE = { long.class.getName(), };
45
46 private MBeansAccessor() {
47 super();
48 }
49
50 static Set<ObjectName> getTomcatThreadPools() {
51 final Set<ObjectName> result = new HashSet<>(
52 MBEAN_SERVER.queryNames(createObjectName("*:type=ThreadPool,*"), null));
53
54 result.removeAll(MBEAN_SERVER.queryNames(
55 createObjectName("*:type=ThreadPool,*,subType=SocketProperties"), null));
56 return result;
57 }
58
59 static Set<ObjectName> getTomcatGlobalRequestProcessors() {
60 return MBEAN_SERVER.queryNames(createObjectName("*:type=GlobalRequestProcessor,*"), null);
61 }
62
63 private static Set<ObjectName> getNioBufferPools() {
64 return MBEAN_SERVER.queryNames(createObjectName("java.nio:type=BufferPool,*"), null);
65 }
66
67 static long getUsedBufferMemory() {
68 if (NIO_BUFFER_POOLS.isEmpty()) {
69 return -1;
70 }
71 long result = 0;
72 try {
73 for (final ObjectName objectName : NIO_BUFFER_POOLS) {
74
75 result += (Long) getAttribute(objectName, "MemoryUsed");
76 }
77 } catch (final JMException e) {
78 throw new IllegalStateException(e);
79 }
80 return result;
81 }
82
83
84
85
86
87
88
89
90
91
92 @SuppressWarnings("unchecked")
93 static <T> T getAttribute(ObjectName name, String attribute) throws JMException {
94 return (T) MBEAN_SERVER.getAttribute(name, attribute);
95 }
96
97 static long getLongFromOperatingSystem(String attribute) {
98 if (!OPERATING_SYSTEM_ATTRIBUTES.contains(attribute)) {
99
100 return -1L;
101 }
102 try {
103 return getAttribute(OPERATING_SYSTEM, attribute);
104 } catch (final JMException e) {
105 throw new IllegalStateException(e);
106 }
107 }
108
109 static double getDoubleFromOperatingSystem(String attribute) {
110 if (!OPERATING_SYSTEM_ATTRIBUTES.contains(attribute)) {
111
112 return -1D;
113 }
114 try {
115 return getAttribute(OPERATING_SYSTEM, attribute);
116 } catch (final JMException e) {
117 throw new IllegalStateException(e);
118 }
119 }
120
121 static long getThreadAllocatedBytes(long threadId) {
122 if (!MBEAN_ALLOCATED_BYTES_ENABLED) {
123 return -1L;
124 }
125 try {
126 return (Long) MBEAN_SERVER.invoke(THREADING, "getThreadAllocatedBytes",
127 new Object[] { threadId }, THREAD_ALLOCATED_BYTES_SIGNATURE);
128 } catch (final JMException e) {
129 throw new IllegalStateException(e);
130 }
131 }
132
133 static Object invoke(ObjectName name, String operationName, Object[] params, Class<?>[] classes)
134 throws JMException {
135 assert name != null;
136 assert operationName != null;
137 assert params != null;
138 assert classes != null;
139 final String[] signature = new String[classes.length];
140 for (int i = 0; i < signature.length; i++) {
141 signature[i] = classes[i].getName();
142 }
143 return MBEAN_SERVER.invoke(name, operationName, params, signature);
144 }
145
146 private static ObjectName createObjectName(String name) {
147 try {
148 return new ObjectName(name);
149 } catch (final MalformedObjectNameException e) {
150
151 throw new IllegalStateException(e);
152 }
153 }
154
155 private static Set<String> getAttributesNames(ObjectName name) {
156 try {
157 final Set<String> result = new HashSet<>();
158 final MBeanInfo mBeanInfo = MBEAN_SERVER.getMBeanInfo(name);
159 final MBeanAttributeInfo[] attributes = mBeanInfo.getAttributes();
160 for (final MBeanAttributeInfo attribute : attributes) {
161 if (attribute.isReadable()) {
162 result.add(attribute.getName());
163 }
164 }
165 return result;
166 } catch (final JMException e) {
167 return Collections.emptySet();
168 }
169 }
170
171 private static boolean isMbeanAllocatedBytesEnabled() {
172 if (getAttributesNames(THREADING).contains("ThreadAllocatedMemoryEnabled")) {
173 try {
174 final boolean supported = getAttribute(THREADING, "ThreadAllocatedMemorySupported");
175 if (supported) {
176 return getAttribute(THREADING, "ThreadAllocatedMemoryEnabled");
177 }
178 } catch (final JMException ex) {
179 throw new IllegalStateException(ex);
180 }
181 }
182 return false;
183 }
184 }
185