blob: eb4957e22759faf490374eb193c4ec121e87fddf [file] [log] [blame]
/****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF licenses this file *
* to you under the Apache License, Version 2.0 (the *
* "License"); you may not use this file except in compliance *
* with the License. You may obtain a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, *
* software distributed under the License is distributed on an *
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
****************************************************************/
package org.apache.james.postage.jmx;
import java.io.IOException;
import java.util.Iterator;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import org.apache.james.postage.SamplingException;
import org.apache.james.postage.execution.Sampler;
import org.apache.james.postage.result.JVMResourcesRecord;
import org.apache.james.postage.result.PostageRunnerResult;
/**
* the peek into the James JVM is done using the build-in management (JMX) of J2SE 5 (and probably later)
* you must start James under a J2SE 5 compatible JVM and
* add some system properties to the phoenix.[sh|bat] file (all on one line):<br/>
* <br/>
* <code>
* JVM_OPTS="-Djava.ext.dirs=$JVM_EXT_DIRS
* -Dcom.sun.management.jmxremote
* -Dcom.sun.management.jmxremote.ssl=false
* -Dcom.sun.management.jmxremote.authenticate=false
* -Dcom.sun.management.jmxremote.port=10201 "
* </code>
* <br/>
* this class does not even compile on Java versions before JSE 5.<br/>
*/
public class JVMResourceSampler implements Sampler {
private String host;
private int port;
private PostageRunnerResult results;
private MBeanServerConnection mBeanServerConnection;
public JVMResourceSampler(String host, int port, PostageRunnerResult results) {
this.host = host;
this.port = port;
this.results = results;
}
public void connectRemoteJamesJMXServer() throws SamplingException {
String serviceURL = "service:jmx:rmi:///jndi/rmi://" + this.host + ":" + this.port + "/jmxrmi";
try {
JMXServiceURL jmxServiceURL = new JMXServiceURL(serviceURL);
JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxServiceURL, null);
this.mBeanServerConnection = jmxConnector.getMBeanServerConnection();
} catch (IOException e) {
throw new SamplingException("could not connect to " + serviceURL, e);
}
}
private void takeMemorySample(JVMResourcesRecord jvmResourcesRecord) throws SamplingException {
CompositeDataSupport data = null;
data = getRemoteAttributeValue("java.lang:type=Memory", "HeapMemoryUsage");
jvmResourcesRecord.setMemoryCommitted(((Long)data.get("committed")).longValue());
jvmResourcesRecord.setMemoryInit(((Long)data.get("init")).longValue());
jvmResourcesRecord.setMemoryMax(((Long)data.get("max")).longValue());
jvmResourcesRecord.setMemoryUsed(((Long)data.get("used")).longValue());
}
private void takeThreadingSample(JVMResourcesRecord jvmResourcesRecord) throws SamplingException {
AttributeList attributes = getRemoteThreadingAttributeValues();
jvmResourcesRecord.setThreadCountCurrent(((Integer)getAttributeValue(attributes, "ThreadCount")).longValue());
jvmResourcesRecord.setThreadCountPeak(((Integer)getAttributeValue(attributes, "PeakThreadCount")).longValue());
jvmResourcesRecord.setThreadCountTotalStarted(((Long)getAttributeValue(attributes, "TotalStartedThreadCount")).longValue());
}
private CompositeDataSupport getRemoteAttributeValue(String jmxObjectName, String attributeName) throws SamplingException {
CompositeDataSupport data;
try {
ObjectName name = new ObjectName(jmxObjectName);
data = (CompositeDataSupport)this.mBeanServerConnection.getAttribute(name, attributeName);
} catch (IOException e) {
throw new SamplingException("lost connection to JMX server", e);
} catch (Exception e) {
throw new SamplingException("failed to take memory sample", e);
}
return data;
}
private AttributeList getRemoteThreadingAttributeValues() throws SamplingException {
try {
ObjectName name = new ObjectName("java.lang:type=Threading");
String[] attributeNames = new String[] {"PeakThreadCount", "ThreadCount", "TotalStartedThreadCount"};
AttributeList attributes = this.mBeanServerConnection.getAttributes(name, attributeNames);
return attributes;
} catch (IOException e) {
throw new SamplingException("lost connection to JMX server", e);
} catch (Exception e) {
throw new SamplingException("failed to take memory sample", e);
}
}
private Object getAttributeValue(AttributeList attributeList, String key) {
for (Iterator<?> iterator = attributeList.iterator(); iterator.hasNext();) {
Attribute attribute = (Attribute)iterator.next();
if (attribute.getName().equals(key)) return attribute.getValue();
}
return null;
}
public void doSample() throws SamplingException {
JVMResourcesRecord jvmResourcesRecord = new JVMResourcesRecord();
takeMemorySample(jvmResourcesRecord);
takeThreadingSample(jvmResourcesRecord);
this.results.addJVMResult(jvmResourcesRecord);
}
}