摘要:运行时修改字节码需求在运行时动态修改某个类的字节码文件,不重启服务器。方案字节码修改框架有很多第三方的字节码修改框架,由于前期接触了产品所以决定使用框架,相对而言更为简单,但是效率较低。
运行时修改字节码
需求:在运行时动态修改某个类的字节码文件,不重启服务器。
方案:asm/javaassist + agent+Instrumentation
1.字节码修改框架有很多第三方的字节码修改框架,由于前期接触了apm 产品pinpoint,所以决定使用asm/javaassist 框架,相对而言javaasist更为简单,但是效率较低。
ASM框架概述:
ASM有两种处理字节码的API分别是:
The ASM library provides two APIs for generating and transforming compiled
classes: the core API provides an event based representation of classes, while
the tree API provides an object based representation.
可以类比解析xml
These two APIs can be compared to the Simple API for XML (SAX) and
Document Object Model (DOM) APIs for XML documents: the event based
API is similar to SAX, while the object based API is similar to DOM. The
object based API is built on top of the event based one, like DOM can be
provided on top of SAX.
ASM字节码修改demo:
github:https://github.com/chengbingh...
ASM 十分底层,比如我们要生成一个包含几个熟悉和一个方法的接口,其代码如下:
public static void main(String[] args) throws IOException { ClassWriter cw = new ClassWriter(0); cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT + Opcodes.ACC_INTERFACE, "com/hcb/asm/generate1/Comparable", null, "java/lang/Object", new String[]{"com/hcb/asm/generate123"}); cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "LESS", "I", null, new Integer(0)).visitEnd(); cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "EQUAL", "I", null, new Integer(1)).visitEnd(); cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "GREATER", "I", null, new Integer(2)).visitEnd(); cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "compareTo", "(Ljava/lang/Object;)I", null, null).visitEnd(); cw.visitEnd(); byte[] b = null; b = cw.toByteArray(); //将上述生成的byts 写入一个XX.class 文件中,再通过一个反编译软件就可以看到生成的类。 File file = new File("Comparable1.class"); FileOutputStream fos = new FileOutputStream(file); fos.write(b); fos.close(); }
如果操作不当会产生一些奇怪的字节码,比如下面的这个类,其方法和属性都重复了:
javaasist框架demo:
github:https://github.com/chengbingh...
上述demo展示了如何使用javaassist修改字节码.
**
2. agent说明java 提供了agent可以用来修改字节码,有两个修改时机,一个是class文件加载进虚拟机时,一个是在runtime。
可以通过参数:-javaagent 指定agent jar 包位置,其实在jdk 中有一个示例jar,以jdk1.8为例,在JRE_HOEM/lib/management-agent.jar
这是一个空的jar包,但是其中有manifest.mf的写法。
Premain-Class: 对应是在加载进jvm时。
我们以pingpoint1.7.1为参考:
pinpoint的agent 指定的一个启动参数是:
-javaagent:C:/kingdee/tomcat/apache-tomcat-8.0.48_ppagent/agent-hcb/pinpoint-bootstrap-1.7.1.jar
我们注意到premain-class指定的class有一个方法premain,这个方法即入口函数
Agent-Class:对应运行时。
3.运行时修改字节码案例github:地址:
修改工程:https://github.com/chengbingh...
测试工程:https://github.com/chengbingh...
UpdateClazz的main函数中根据某虚拟机的pid将agent 的jar包load到agent.
agent jar 包的manifest 文件中指定了agentMain方法所在的类
AgentMain 的agentMain方法中调用Transformer修改修改字节码,案例中使用javaasist修改字节码。
测试步骤是:
访问启动tomcat访问对于servlet
UpdateClazz修改字节码(可以用jps命令获取pid)
再次访问
发现已经修改
相关微信公众号:
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/69701.html
摘要:实际上并未引入太多新特性,不过有一个新特性最引人注目等了这么久终于支持类型推断了,那么今天就来看一看的类型推断,和其他语言相比有哪些异同吧。本次更新也支持了类型推断,对于这种重量级语言来说还是一件值得高兴的事。 0x01 Java 10简介 自从有了校内的下载网站,很少上Oracle官网下载JDK了,结果前两天听钟神说Java 10都出来了2333。干IT这行还真是要与时俱进啊,那就...
阅读 3431·2021-09-30 09:59
阅读 2174·2021-09-13 10:34
阅读 560·2019-08-30 12:58
阅读 1485·2019-08-29 18:42
阅读 2163·2019-08-26 13:44
阅读 2905·2019-08-23 18:12
阅读 3304·2019-08-23 15:10
阅读 1605·2019-08-23 14:37