View Javadoc

1   /*****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  
21  package org.apache.james.postage.jmx;
22  
23  import org.apache.james.postage.execution.Sampler;
24  import org.apache.james.postage.result.PostageRunnerResult;
25  import org.apache.james.postage.result.JVMResourcesRecord;
26  import org.apache.james.postage.SamplingException;
27  
28  import javax.management.remote.JMXConnector;
29  import javax.management.remote.JMXServiceURL;
30  import javax.management.remote.JMXConnectorFactory;
31  import javax.management.openmbean.CompositeDataSupport;
32  import javax.management.AttributeList;
33  import javax.management.MBeanServerConnection;
34  import javax.management.ObjectName;
35  import javax.management.Attribute;
36  import java.io.IOException;
37  import java.util.Iterator;
38  
39  /***
40   * the peek into the James JVM is done using the build-in management (JMX) of J2SE 5 (and probably later)
41   * you must start James under a J2SE 5 compatible JVM and
42   * add some system properties to the phoenix.[sh|bat] file (all on one line):<br/>
43   * <br/>
44   * <code>
45   * JVM_OPTS="-Djava.ext.dirs=$JVM_EXT_DIRS
46   *           -Dcom.sun.management.jmxremote
47   *           -Dcom.sun.management.jmxremote.ssl=false
48   *           -Dcom.sun.management.jmxremote.authenticate=false
49   *           -Dcom.sun.management.jmxremote.port=10201 "
50   * </code>
51   * <br/>
52   * this class does not even compile on Java versions before JSE 5.<br/>
53   */
54  public class JVMResourceSamplerWorker implements Sampler {
55  
56      private String m_host;
57      private int m_port;
58      private PostageRunnerResult m_results;
59  
60      private MBeanServerConnection m_mBeanServerConnection;
61  
62      public JVMResourceSamplerWorker(String host, int port, PostageRunnerResult results) {
63          m_host = host;
64          m_port = port;
65          m_results = results;
66      }
67  
68      public void connectRemoteJamesJMXServer() throws SamplingException {
69          String serviceURL = "service:jmx:rmi:///jndi/rmi://" + m_host + ":" + m_port + "/jmxrmi";
70          try {
71              JMXServiceURL jmxServiceURL = new JMXServiceURL(serviceURL);
72              JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxServiceURL, null);
73              m_mBeanServerConnection = jmxConnector.getMBeanServerConnection();
74          } catch (IOException e) {
75              throw new SamplingException("could not connect to " + serviceURL, e);
76          }
77      }
78  
79      private void takeMemorySample(JVMResourcesRecord jvmResourcesRecord) throws SamplingException {
80          CompositeDataSupport data = null;
81          data = getRemoteAttributeValue("java.lang:type=Memory", "HeapMemoryUsage");
82          jvmResourcesRecord.setMemoryCommitted(((Long)data.get("committed")).longValue());
83          jvmResourcesRecord.setMemoryInit(((Long)data.get("init")).longValue());
84          jvmResourcesRecord.setMemoryMax(((Long)data.get("max")).longValue());
85          jvmResourcesRecord.setMemoryUsed(((Long)data.get("used")).longValue());
86      }
87  
88      private void takeThreadingSample(JVMResourcesRecord jvmResourcesRecord) throws SamplingException {
89          CompositeDataSupport data = null;
90          AttributeList attributes = getRemoteThreadingAttributeValues();
91          jvmResourcesRecord.setThreadCountCurrent(((Integer)getAttributeValue(attributes, "ThreadCount")).longValue());
92          jvmResourcesRecord.setThreadCountPeak(((Integer)getAttributeValue(attributes, "PeakThreadCount")).longValue());
93          jvmResourcesRecord.setThreadCountTotalStarted(((Long)getAttributeValue(attributes, "TotalStartedThreadCount")).longValue());
94      }
95  
96      private CompositeDataSupport getRemoteAttributeValue(String jmxObjectName, String attributeName) throws SamplingException {
97          CompositeDataSupport data;
98          try {
99              ObjectName name = new ObjectName(jmxObjectName);
100             data = (CompositeDataSupport)m_mBeanServerConnection.getAttribute(name, attributeName);
101         } catch (IOException e) {
102             throw new SamplingException("lost connection to JMX server", e);
103         } catch (Exception e) {
104             throw new SamplingException("failed to take memory sample", e);
105         }
106         return data;
107     }
108 
109     private AttributeList getRemoteThreadingAttributeValues() throws SamplingException {
110         try {
111             ObjectName name = new ObjectName("java.lang:type=Threading");
112             String[] attributeNames = new String[] {"PeakThreadCount", "ThreadCount", "TotalStartedThreadCount"};
113             AttributeList attributes = m_mBeanServerConnection.getAttributes(name, attributeNames);
114             return attributes;
115         } catch (IOException e) {
116             throw new SamplingException("lost connection to JMX server", e);
117         } catch (Exception e) {
118             throw new SamplingException("failed to take memory sample", e);
119         }
120     }
121 
122     private Object getAttributeValue(AttributeList attributeList, String key) {
123         for (Iterator iterator = attributeList.iterator(); iterator.hasNext();) {
124             Attribute attribute = (Attribute)iterator.next();
125             if (attribute.getName().equals(key)) return attribute.getValue();
126         }
127         return null;
128     }
129 
130     public void doSample() throws SamplingException {
131         JVMResourcesRecord jvmResourcesRecord = new JVMResourcesRecord();
132         takeMemorySample(jvmResourcesRecord);
133         takeThreadingSample(jvmResourcesRecord);
134         m_results.addJVMResult(jvmResourcesRecord);
135     }
136 }