javaagent demo程序(使用javaagent实现字节码层面的代码修改)
2017-12-27 23:56
701 查看
javaagent demo程序(使用javaagent实现字节码层面的代码修改)
本文主要讲解一下内容:1、javaagent的作用。
2、一个可用的javaagent demo程序。
3、引出类似的工具bytebuddy和asm。
好,下面上货。
一、首先说一下javaagent 的作用。javaagent是一种能够在不影响正常编译的情况下,修改字节码。java作为一种强类型的语言,不通过编译就不能能够进行jar包的生成。而有了javaagent技术,就可以在字节码这个层面对类和方法进行修改。同时,也可以把javaagent理解成一种代码注入的方式。但是这种注入比起spring的aop更加的优美。
二、一个javaagent demo程序
1、首先创建agent。作为agent的jar包必须有两个要求。
一个是必须实现premain方法,另一个是必须在MANIFEST.MF文件中有Premain-Class。
先看一下agent的实现。
package com.xueyou.demo.agent; import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod; import javassist.CtNewMethod; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.security.ProtectionDomain; public class FirstAgent implements ClassFileTransformer { public final String injectedClassName = "com.xueyou.agentdemo.App"; public final String methodName = "hello"; public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { className = className.replace("/", "."); // System.out.println(className); if (className.equals(injectedClassName)) { CtClass ctclass = null; try { ctclass = ClassPool.getDefault().get(className);// 使用全称,用于取得字节码类<使用javassist> CtMethod ctmethod = ctclass.getDeclaredMethod(methodName);// 得到这方法实例 ctmethod.insertBefore("System.out.println(11111111);"); return ctclass.toBytecode(); } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); } } return null; } }
然后需要在premain中对这个FirstAgent进行加载,具体代码如下:
package com.xueyou.demo; import com.xueyou.demo.agent.FirstAgent; import java.lang.instrument.Instrumentation; /** * Hello world! */ public class App { public static void premain(String agentOps, Instrumentation inst) { System.out.println("=========premain方法执行========"); System.out.println(agentOps); // 添加Transformer inst.addTransformer(new FirstAgent()); } }
下面比较重要的是pom文件中如何对jar包进行build,因为需要自动的在MANIFEST.MF文件中添加Premain-Class,所以这里需要在pom中添加插件并且指定premain-class。
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> <encoding>utf-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.0.0</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <manifestEntries> <Premain-Class>com.xueyou.demo.App</Premain-Class> </manifestEntries> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build>
这样打包之后能够在jar包内看到对应的premain-class。
Manifest-Version: 1.0 Premain-Class: com.xueyou.demo.App Archiver-Version: Plexus Archiver Built-By: wuxueyou Created-By: Apache Maven 3.3.9 Build-Jdk: 1.8.0_101
2、现在我们编写这个FirstAgent要拦截的类(也可以说是要加强的类)
package com.xueyou.agentdemo; /** * Hello world! */ public class App { public static void main(String[] args) { hello(); } public static void hello() { System.out.println("this is agent-demo output"); } }
3、编写好程序后,在运行的时候需要指定javaagent。
这里有两种方式指定javaagent:
1)使用命令行:java -javaagent:XXX.jar ddd.jar
2)使用idea的vm option选项。
这里需要配置的就是-javaagent:agent-1.0.-SNAPSHOT.jar即可。
4、运行查看结果:
三、虽然javaagent可以完成对类的拦截和增强,但是在使用的时候还是有些困难,需要一直中string的方式进行代码的编写,而且调试的时候也不是很方便。所以,如果允许的话,可以使用bytebuddy和asm。
相关文章推荐
- 使用JVM TI技术插装字节码,实现Java代码执行控监Agent
- [编写高质量代码:改善java程序的151个建议]建议43 避免对象浅拷贝; 建议44:推荐使用序列化实现对象的深拷贝
- 使用Eclipse-jee3.6版本部署web项目已实现修改java代码不用重启
- 使用Java中的JNI技术将C/C++程序嵌入到Java代码中实现Hello World
- 用Swig将c/c++程序转为java代码(使用swig实现java调用c、c++的方法)
- 简单完整的代码,通过这个代码你将对RSA加密算法在Java中的实现方法有一个初步的了解,这个类,你可以直接使用,水平高的,就自己修改完善下代码。
- Java【代码】使用jspSmartUpload实现文件上传demo
- [编写高质量代码:改善java程序的151个建议]建议43 避免对象浅拷贝; 建议44:推荐使用序列化实现对象的深拷贝
- java agent 使用及实现代码
- JAVA 实现多文件同时操作 程序代码
- 使用JAVA实现签名验证示例程序
- 使用eclipse的JDT实现JAVA代码格式化功能
- 如何使用java程序实现windows锁屏
- 使用C/C++实现Socket聊天程序(代码+实验报告)
- 使用JNI技术实现JAVA程序调用dll
- 实现验证码控件代码验证控件,方便使用验证码(修改)
- 【asp.net 】使用js结合hidden控件实现在后台运行一段程序后提示确认,确认通过后继续执行后台代码~~~
- 使用C/C++实现Socket聊天程序(代码+实验报告)
- 使用Java程序来实现HTTP文件的队列下载
- C Java PHP Perl Python的程序代码美化工具使用