/* * ALMA - Atacama Large Millimiter Array * (c) Universidad Tecnica Federico Santa Maria, 2008 * Copyright by ESO (in the framework of the ALMA collaboration), * All rights reserved * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ package alma.acs.monitoring; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.lang.management.ManagementFactory; import java.util.Date; import java.util.Timer; import java.util.TimerTask; import javax.management.MBeanServerConnection; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; import com.sun.tools.attach.AttachNotSupportedException; import com.sun.tools.attach.VirtualMachine; /** * Simple program that connects to a JVM running on the same host, * given the classname that contains the main method, and calls the * garbage collector periodically over it. * * @author rtobar * @since ACS 9.0 */ public class GCJMXClient { private static final String LOCAL_CONNECTOR_ADDRESS = "com.sun.management.jmxremote.localConnectorAddress"; private VirtualMachine _vm; private MBeanServerConnection _remote; public GCJMXClient(String className) { int pid = 0; try { pid = getPID(className); } catch (IOException e) { System.err.println("Error while getting remote PID!: " + e.getMessage()); System.exit(1); } if( pid == 0 ) { System.err.println("Couldn't find process for class " + className); System.exit(1); } else { // We have found the PID :) try { _vm = getVM(pid); } catch (IOException e) { System.err.println("Can't connect to remote VM: " + e.getMessage()); System.exit(1); } catch (AttachNotSupportedException e) { System.err.println("Can't attach to the remote JVM: " + e.getMessage()); System.exit(1); } } } public void connect() throws Exception { // get the connector address String connectorAddress = _vm.getAgentProperties().getProperty(LOCAL_CONNECTOR_ADDRESS); // no connector address, so we start the JMX agent if (connectorAddress == null) { String agent = _vm.getSystemProperties().getProperty("java.home") + File.separator + "lib" + File.separator + "management-agent.jar"; _vm.loadAgent(agent); // agent is started, get the connector address connectorAddress = _vm.getAgentProperties().getProperty(LOCAL_CONNECTOR_ADDRESS); if ( connectorAddress == null ) { System.err.println("Cannot connect :("); System.exit(1); } } JMXServiceURL remoteURL = new JMXServiceURL(connectorAddress); JMXConnector connector = null; try { connector = JMXConnectorFactory.connect(remoteURL); } catch (IOException e) { System.err.println("Can't connect to the remote URL"); System.exit(-1); } try { _remote = connector.getMBeanServerConnection(); } catch (IOException e) { System.err.println("Can't get a connection to the remote MBeanServer"); System.exit(-1); } } public MBeanServerConnection getRemote() { return _remote; } private VirtualMachine getVM(int pid) throws AttachNotSupportedException, IOException { if( _vm == null ) { VirtualMachine vm = VirtualMachine.attach(String.valueOf(pid)); _vm = vm; } return _vm; } private int getPID(String className) throws IOException { String s; Integer remotePID = null; Process p = Runtime.getRuntime().exec("jps -lm"); BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())); // read the output from the command while ((s = stdInput.readLine()) != null) { String[] ss = s.split("[\t ]+"); if (ss.length > 1) { if (ss[1].equals(className)) { remotePID = Integer.valueOf(ss[0]); break; } } } stdInput.close(); if( remotePID == null ){ //System.err.println("Can't obtain PID for the given class"); return 0; } return remotePID.intValue(); } public static void main(String[] args) { if( args.length < 2 ) { System.err.println("Must provide 2 arguments: <classname> <interval-in-ms>"); } final GCJMXClient client = new GCJMXClient(args[0]); try { client.connect(); } catch(Exception e) { System.err.println(e.getMessage()); System.exit(1); } ObjectName objName = null; try { objName = new ObjectName(ManagementFactory.MEMORY_MXBEAN_NAME); } catch (MalformedObjectNameException e1) { System.err.println("bad name?"); System.exit(1); } final ObjectName objNameF = objName; Timer timer = new Timer(); TimerTask task = new TimerTask() { public void run() { MBeanServerConnection con = client.getRemote(); try { con.invoke(objNameF, "gc", null, null); System.out.println("Called gc() on remote VM"); } catch (Exception e) { System.err.println("Couldn't call gc() on remote VM"); } } }; timer.scheduleAtFixedRate(task, new Date(), Integer.parseInt(args[1])); } }