javaAgent简单使用

来源:互联网 发布:网络隐私权的法律规定 编辑:程序博客网 时间:2024/06/05 19:43

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 = ManagementFactory.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路径

原创粉丝点击