资讯专栏INFORMATION COLUMN

apm-01-update class at runtime

codeKK / 2873人阅读

摘要:运行时修改字节码需求在运行时动态修改某个类的字节码文件,不重启服务器。方案字节码修改框架有很多第三方的字节码修改框架,由于前期接触了产品所以决定使用框架,相对而言更为简单,但是效率较低。

运行时修改字节码

需求:在运行时动态修改某个类的字节码文件,不重启服务器。

方案: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

相关文章

  • Java 10新特性:类型推断

    摘要:实际上并未引入太多新特性,不过有一个新特性最引人注目等了这么久终于支持类型推断了,那么今天就来看一看的类型推断,和其他语言相比有哪些异同吧。本次更新也支持了类型推断,对于这种重量级语言来说还是一件值得高兴的事。 0x01 Java 10简介 自从有了校内的下载网站,很少上Oracle官网下载JDK了,结果前两天听钟神说Java 10都出来了2333。干IT这行还真是要与时俱进啊,那就...

    afishhhhh 评论0 收藏0
  • Java 异常处理

    摘要:下面是异常处理机制的语法结构业务实现代码输入不合法如果执行块里业务逻辑代码时出现异常,系统自动生成一个异常对象,该对象被提交给运行时环境,这个过程被称为抛出异常。 Java的异常机制主要依赖于try、catch、finally、throw和throws五个关键字, try关键字后紧跟一个花括号括起来的代码块(花括号不可省略),简称try块,它里面放置可能引发异常的代码 catch后对...

    senntyou 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<