/**
* Copyright 2012-2015 Rafal Lewczuk <rafal.lewczuk@jitlogic.com>
*
* ZORKA is free software. You can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* ZORKA 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* ZORKA. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jitlogic.zorka.agent;
import com.jitlogic.zorka.common.util.ZorkaUtil;
import com.jitlogic.zorka.core.AgentConfig;
import com.jitlogic.zorka.core.AgentInstance;
import com.jitlogic.zorka.core.ZorkaControl;
import com.jitlogic.zorka.core.spy.MainSubmitter;
import com.jitlogic.zorka.core.spy.SpyRetransformer;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* This class is responsible for bootstrapping zorka agent.
*
* @author rafal.lewczuk@jitlogic.com
*/
public class AgentMain {
private static volatile AgentInstance instance;
private static boolean supportsRetransform(Instrumentation instrumentation) throws Exception {
for (Method m : instrumentation.getClass().getMethods()) {
if ("isRetransformClassesSupported".equals(m.getName())) {
return (Boolean) m.invoke(instrumentation);
}
}
return false;
}
private static SpyRetransformer instantiateRetransformer(Instrumentation instrumentation, AgentConfig config,
String className) throws Exception {
Class<?> clazz = Class.forName(className);
for (Constructor<?> constructor : clazz.getConstructors()) {
Class<?>[] args = constructor.getParameterTypes();
if (args.length == 2) {
return (SpyRetransformer) constructor.newInstance(instrumentation, config);
}
}
throw new IllegalArgumentException("Cannot instantiate retransformer of class " + className);
}
private static void addTransformer(Instrumentation instrumentation, ClassFileTransformer transformer,
boolean retransformSupported) throws Exception {
Method atm = null;
for (Method m : Instrumentation.class.getMethods()) {
if ("addTransformer".equals(m.getName())) {
atm = m;
if (m.getParameterTypes().length == 2 || !retransformSupported) {
break;
}
}
}
if (atm.getParameterTypes().length == 2) {
atm.invoke(instrumentation, transformer, retransformSupported);
} else {
atm.invoke(instrumentation, transformer);
}
}
/**
* This is entry method of java agent.
*
* @param args arguments (supplied via -javaagent:/path/to/agent.jar=arguments)
* @param instrumentation reference to JVM instrumentation interface
*/
public static void premain(String args, Instrumentation instrumentation) throws Exception {
String home = System.getProperties().getProperty("zorka.home.dir", args);
boolean retransformSupported = supportsRetransform(instrumentation);
AgentConfig config = new AgentConfig(ZorkaUtil.path(home));
instance = new AgentInstance(config, instantiateRetransformer(instrumentation, config,
"com.jitlogic.zorka.core.spy." + (retransformSupported ? "RealSpyRetransformer" : "DummySpyRetransformer")));
instance.start();
if (instance.getConfig().boolCfg("spy", true)) {
addTransformer(instrumentation, instance.getClassTransformer(), retransformSupported);
MainSubmitter.setSubmitter(instance.getSubmitter());
MainSubmitter.setTracer(instance.getTracer());
}
instance.getMBeanServerRegistry().registerZorkaControl(
new ZorkaControl("java", "zorka:type=ZorkaControl,name=ZorkaControl", instance));
}
}