您的位置:首页 > 编程语言 > Java开发

javaAgent简单使用

2017-08-23 20:58 417 查看

javaAgent

记录之前印象中的使用过程记录,感兴趣的可按照套路来实践下。

注意需要使用到tools.jar包

1. 制作hotfix-1.0.jar

Manifest-Version: 1.0

Agent-Class: xxx.xxx.xxxx.JavaDynAgent

Can-Redefine-Classes: true

import java.lang.instrument.Instrumentation;
import org.apache.log4j.Logger;

public class JavaDynAgent {
private static final Logger logger = Logger.getLogger(JavaDynAgent.class);

private static Instrumentation instrumentation;
private static Object lockObject = new Object();

public static void agentmain(String args, Instrumentation inst) {
synchronized(lockObject) {
if(instrumentation == null) {
logger.info("agentmain called, init instrumentation inst");
instrumentation = inst;
}else {
logger.info("agentmain called, already init");
}
}
}

public static Instrumentation getInstrumentation() {
return instrumentation;
}
}


2. 项目调用接口类

import java.io.File;
import java.io.IOException;
import java.lang.instrument.ClassDefinition;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.google.common.base.Preconditions;
import com.google.common.io.Files;
import com.sun.tools.attach.AgentInitializationException;
import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;

public class JavaAgentUtil {

private static final Logger logger = Logger.getLogger(JavaAgentUtil.class);

private static String basePath;

private static String classesPath;
private static String jarPath;
private static VirtualMachine vm;
private static String pid;

static {
basePath = getBasePath();

//classesPath = basePath + "classes" + "/";
classesPath = basePath + "hotfix" + "/";
jarPath = basePath + "lib" + "/";

// 当前进程pid
String name = Managem
a753
entFactory.getRuntimeMXBean().getName();
pid = name.split("@")[0];

logger.info("JavaAgentUtil init classesPath = " + classesPath + " jarPath = " + jarPath);
}

public static String getBasePath() {
String clsPath = JavaAgentUtil.class.getResource("").getPath();
String[] strArr = clsPath.split("classes|lib");
return strArr[0];
}

public static boolean javaAgent(String root, String[] classArr) throws ClassNotFoundException, IOException, UnmodifiableClassException, AttachNotSupportedException, AgentLoadException, AgentInitializationException
{
try {
// 虚拟机加载
logger.info("init agent attach jvm");

vm = VirtualMachine.attach(pid);
vm.loadAgent(jarPath + "hotfix-1.0.jar");

Instrumentation instrumentation = JavaDynAgent.getInstrumentation();
Preconditions.checkNotNull(instrumentation, "initInstrumentation must not be null");

StringBuilder tmpStr = new StringBuilder();
// 1.整理需要重定义的类
List<ClassDefinition> classDefList = new ArrayList<ClassDefinition>();
for (String className : classArr) {
Class<?> c = Class.forName(className);
String classPath = (StringUtils.isNotBlank(root) ? root : classesPath) + className.replace(".", "/") + ".class";
byte[] bytesFromFile = Files.toByteArray(new File(classPath));
ClassDefinition classDefinition = new ClassDefinition(c, bytesFromFile);
classDefList.add(classDefinition);

tmpStr.append(className);
}

// 2.redefine
JavaDynAgent.getInstrumentation().redefineClasses(classDefList.toArray(new ClassDefinition[classDefList.size()]));

logger.info(" redefine classes success classArr = " + tmpStr.toString());

return true;
}
catch (Exception e) {
logger.error("javaAgent err when redefine class msg = " + e.getMessage());
} finally {
if (vm != null) {
vm.detach();
logger.info("detach agent jvm");
}
}
return false;
}

// reload class files
public static boolean loadClass(String[] names){
try {
return javaAgent(null, names);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnmodifiableClassException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AttachNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AgentLoadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AgentInitializationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
}


3. 调用前面接口例子

String[] clsNames = fixnames.split("\\|");
JavaAgentUtil.loadClass(clsNames);


其中fixnames为以|分割的字符串

例如:class1路径|class2路径
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: