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 }