
org.perfcake.agent.PerfCakeAgent Maven / Gradle / Ivy
/*
* -----------------------------------------------------------------------\
* PerfCake
*
* Copyright (C) 2010 - 2016 the original author or authors.
*
* Licensed 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.
* -----------------------------------------------------------------------/
*/
/*
* Copyright 2010-2013 the original author or authors.
*
* Licensed 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.perfcake.agent;
import com.sun.tools.attach.VirtualMachine;
/**
* Java implementation of a PerfCake agent that can be used to monitor tested system's JVM.
*
* Starts a thread with a socket server listening on a specified host and port and is used
* by PerfCake's reporting (class org.perfcake.reporting.reporters.MemoryUsageReporter) to gather memory usage data
* and to control garbage collection and heap dump activities needed by the reporter.
*
* To attach the agent to the tested system's JVM, append the following JVM argument to
* the executing java command or use JAVA_OPTS environment variable:
*
* "... -javaagent:<perfcake_agent_jar>=hostname=<hostname>,port=<port>
* where perfcake_jar_path
is a path to PerfCake JAR archive, hostname
and port
* specifies agent's socket.
*
* It is also possible to attach to a running JVM:
*
* java -cp ${JAVA_HOME}/lib/tools.jar:<perfcake_agent_jar> org.perfcake.agent.PerfCakeAgent <PID> hostname=<hostname>,port=<port>
*
*
*
*
* Command
* Description
*
*
*
*
* "{@link AgentCommand#FREE FREE}"
* Returns the amount of free memory in the Java Virtual Machine.
*
*
* "{@link AgentCommand#USED USED}"
* Returns the amount of used memory in the Java Virtual Machine.
*
*
* "{@link AgentCommand#TOTAL TOTAL}"
* Returns the amount of total memory in the Java Virtual Machine.
*
*
* "{@link AgentCommand#MAX MAX}"
* Returns the maximum amount of memory that the Java Virtual Machine will attempt to use.
*
*
* "{@link AgentCommand#DUMP DUMP}(:<dump-file>)"
* Initiates a heap dump into dump-file
. dump-file
is optional - if not provided,
* the file name would be generated as "dump-" + {@link java.lang.System#currentTimeMillis()} + ".bin"
.
*
*
* "{@link AgentCommand#GC GC}"
* Calls {@link System#gc()}.
*
*
*
*
* @author Pavel Macík
* @author Martin Večeřa
* @see AgentCommand
*/
public class PerfCakeAgent {
/**
* Default encoding of the input and output streams.
*/
public static final String DEFAULT_ENCODING = "UTF-8";
/**
* Default agent port.
*/
public static final int DEFAULT_PORT = 8850;
/**
* There should be no instance of a utility class.
*/
private PerfCakeAgent() {
}
/**
* {@link PerfCakeAgent}'s pre-main method.
*
* @param agentArgs
* Agent arguments.
* @see java.lang.instrument
*/
public static void premain(final String agentArgs) {
final Thread agentThread = new Thread(new AgentThread(agentArgs));
agentThread.setDaemon(true);
agentThread.start();
}
public static void agentmain(final String agentArgs, final java.lang.instrument.Instrumentation inst) {
premain(agentArgs);
}
private static void printUsage() {
System.out.println("PerfCake Agent -- monitor memory usage of the hosting JVM");
System.out.println("Usage: java -jar perfcake-agent.jar ");
System.out.println(" JVM process ID to attach to");
System.out.println(" voluntary, available args are hostname=,port=");
System.out.println(" These arguments specify where to bind the agent.");
}
/**
* Starts the agent from command line allowing it to bind to a running process.
*
* @param args Command line arguments.
*/
public static void main(final String... args) {
if (args.length < 1) {
printUsage();
System.exit(1);
}
try {
final int pid = Integer.parseInt(args[0]);
} catch (NumberFormatException nfe) {
printUsage();
System.out.println("First argument is not a number.");
System.exit(2);
}
final StringBuilder agentArgs = new StringBuilder();
for (int i = 1; i < args.length; i++) {
agentArgs.append(args[i]);
agentArgs.append(" ");
}
try {
final VirtualMachine vm = VirtualMachine.attach(args[0]);
final String path = PerfCakeAgent.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath();
vm.loadAgent(path, agentArgs.toString());
vm.detach();
} catch (Exception e) {
System.err.println("Unable to attach to the PID " + args[0]);
e.printStackTrace(System.err);
System.exit(3);
}
System.out.println("PerfCake Agent successfully attached.");
}
}