利用javaagent,javassist 进行热修补

使用命令:

1 java -javaagent:agent.jar -jar target.jar

注意事项: 

  1. -javaagent:agent.jar "-javaagent:"后面没有空格,紧接着的是agent.jar
  2. javaagent资料可以google. 

agent.jar注意事项

  • MANIFEST.MF文件内容
    Manifest-Version: 1.0
    Premain-Class: com.xiaobai.Main
    Can-Redefine-Classes: true

注意每个":" 后面都有一个空格,不加报错

  • 外部jar引用注意. 
    要打包进agent.jar,不要以jar形式存在,否则报错找不到class文件

javassist资料不介绍了,网上很多.

例子:

  • Mian.java
    package com.xiaobai;
    
    import java.lang.instrument.Instrumentation;
    
    public class Main {
        public static void premain(String agentOps, Instrumentation inst) {
            inst.addTransformer(new NewTransformer());
        }
    }
    

      

  • NewTransformer.java
    package com.xiaobai;
    
    import javassist.*;
    
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.lang.instrument.ClassFileTransformer;
    import java.lang.instrument.IllegalClassFormatException;
    
    import java.security.ProtectionDomain;
    
    /**
     * description: Transformer
     * author: xiaobai
     * data: 2016/8/30
     */
    public class NewTransformer implements ClassFileTransformer {
    
    
        @Override
        public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
            className = className.replace("/", ".");
            if (!className.equals("com.pnfsoftware.jeb.client.AbstractClientContext"))return null;
            try {
                ClassPool classPool=ClassPool.getDefault();
                ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(classfileBuffer);
                CtClass clazz=classPool.makeClass(byteArrayInputStream);
                CtMethod[] methods=clazz.getMethods();
                for (CtMethod method:methods){
                    if (method.getName().equals("ping")){
                        return fixMethod(clazz,method.getName());
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return new byte[0];
        }
        private byte[] fixMethod(CtClass clazz,String oldmethodName){
            try {
                CtMethod method=clazz.getDeclaredMethod(oldmethodName);
                StringBuilder bodyStr = new StringBuilder();
                bodyStr.append("{");
                bodyStr.append("System.out.println(\"开始热补丁\");\n");
                bodyStr.append("return 0;");
                bodyStr.append("}");
                method.setBody(bodyStr.toString());
                return clazz.toBytecode();
            } catch (NotFoundException e) {
                e.printStackTrace();
            } catch (CannotCompileException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
    }

效果图: 

 

posted @ 2016-08-31 16:13  xiaobaiyey  阅读(853)  评论(0编辑  收藏  举报