使用命令:
1 java -javaagent:agent.jar -jar target.jar
注意事项:
- -javaagent:agent.jar "-javaagent:"后面没有空格,紧接着的是agent.jar
- 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; } }
效果图: