使用javassist对.class文件进行修改-阿里云开发者社区

开发者社区> boxti> 正文

使用javassist对.class文件进行修改

简介:
+关注继续查看

最近重新再看<Inside JVM>,对JAVA编译成的字节码结构很感兴趣,希望找个工具能够对.class文件进行的解析和查看。没找到,倒发现javaassist可以对字节码进行操作和修改。此工具是JBOSS项目的一部分,JBOSS实现AOP的基础。呵呵,开眼界了,原来我们可以直接对字节码文件进行修改,哪怕不知道源文件(跟反编译完全不同)。一个简单例子:

import javassist.*;
class Hello {
    public void say() {
        System.out.println("Hello");
    }
}

public class Test {
    public static void main(String[] args) throws Exception {
        ClassPool cp = ClassPool.getDefault();
        CtClass cc = cp.get("Hello");
        CtMethod m = cc.getDeclaredMethod("say");
        m.setBody("{System.out.println(/"shit/");}");
        m.insertBefore("System.out.println(/"fuck/");");
        Class c = cc.toClass();
        Hello h = (Hello)c.newInstance();
        h.say();
    }
}

编译运行此文件,输出:

fuck

shit

我们在

 CtMethod m = cc.getDeclaredMethod("say");
  m.setBody("{System.out.println(/"shit/");}");

  m.insertBefore("System.out.println(/"fuck/");");

修改了say()方法,改成了

System.out.println("fuck");

System.out.println("shit");

这里的ClassPool是CtClass的容器,它读取class文件,并根据要求保存CtClass的结构以便日后使用,默认状态下是从当前的类装载器获得,当然你可以指定:

pool.insertClassPath("/usr/local/javalib");

当然,不仅仅是修改方法,你还可以新建一个class,利用makeClass()方法,如:

ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass("Point");

还可以新增方法,下面是sample里的一个例子,同样的:

package sample;

import javassist.*;
import java.lang.reflect.*;

/*
   A very simple sample program

   This program overwrites sample/Test.class (the class file of this
   class itself) for adding a method g().  If the method g() is not
   defined in class Test, then this program adds a copy of
   f() to the class Test with name g().  Otherwise, this program does
   not modify sample/Test.class at all.

   To see the modified class definition, execute:

   % javap sample.Test

   after running this program.
*/
public class Test {
    public int f(int i) {
     i++;
    return i;
    }

    public static void main(String[] args) throws Exception {
 ClassPool pool = ClassPool.getDefault();

 CtClass cc = pool.get("sample.Test");
 Test test=new Test();
 Class c=test.getClass();
 Method []method=c.getDeclaredMethods();
 for(int i=0;i<method.length;i++){
  System.out.println(method[i]);
 }
 try {
     cc.getDeclaredMethod("g");
     System.out.println("g() is already defined in sample.Test.");
 }
 catch (NotFoundException e) {
     /* getDeclaredMethod() throws an exception if g()
      * is not defined in sample.Test.
      */
     CtMethod fMethod = cc.getDeclaredMethod("f");
     CtMethod gMethod = CtNewMethod.copy(fMethod, "g", cc, null);
     cc.addMethod(gMethod);
     cc.writeFile(); // update the class file
     System.out.println("g() was added.");
 }
    }
}
第一次运行时,因为Test里并没有g()方法,所以执行

 CtMethod fMethod = cc.getDeclaredMethod("f");
     CtMethod gMethod = CtNewMethod.copy(fMethod, "g", cc, null);  //把f方法复制给g
     cc.addMethod(gMethod);
     cc.writeFile(); //更新class文件

     System.out.println("g() was added.");
打印:g() was added

第2次运行时,因为以上步骤已经在class文件中增加了一个g方法,所以

 System.out.println("g() is already defined in sample.Test.");
打印:g() is already defined in sample.Test

 

Javassist不仅能修改你自己的class文件,而且可以同样修改JDK自带的类库(废话,类库也是人写的^_^)具体请看它的tutorial

文章转自庄周梦蝶  ,原文发布时间5.17

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
如何在 Kubernetes 环境中搭建 MySQL(四):使用 StorageClass 挂接 RBD
MySQL + Kubernetes 1. 简介 在系列文章的第三篇中,讲到了如何使用 PV 和 PVC 挂载 RBD 上建立好的块存储镜像,但这还是不足以满足 cloud native 环境下的需求,试想如果部署一个应用,需要申请十个 R...
1460 0
【玩转ElasticSearch】降维打击!使用ElasticSearch作为时序数据库
本篇分享最近把ElasticSearch当作时序数据库来用的心得。• 需求需求是这样的:提供一个后台,选用户画像标签(多选),点确认后弹出“选出了xxx个用户”,再继续点就把用户dump出来、推送消息。现在要做这个后台的数据仓库层。详细分析一下需求:1. 我们的用户画像走流式计算,每秒大量更新,所以对插入/更新性能要求很高。2. 查询条件翻译成SQL就是类似 se
8361 0
【Java】使用javaassist修改jar包
由于工作需要,可能会涉及到一些需要对第三方的一些jar包与源码进行修改的情况,这个时候javaassist就可以派上用场。 javaassist是一个开源的编辑、修改、创建字节码的类库,它在JBoos项目的AOP框架中发挥了很大的作用。不过我们这次仅仅使用它的修改class的功能。 1 准备工具 1.1 需要用到的工具 1.javaassist.jar 修改class字节码,修改类
6845 0
Java Class类的使用 和 动态加载类
Class类 1)在面向对象的世界里,万事万物皆对象。 类是对象,类是java.lang.Class类的实例对象。 There is a class named Class 2)Foo的实例对象如何表示 Foo foo1=new Foo();//foo1就表示出来了 ...
622 0
【技术贴】解决Eclipse编译java源文件之后没有生成class文件|找不到class文件
【技术贴】解决Eclipse编译java源文件之后没有生成class文件|找不到class文件   今天遇到的,非常恶心,项目下有个红叉叉,因为是公司的老项目,1.4的jdk,我把工程导入后,发现没有报错,但是有小红叉,自动保存代码编译完java源文件之后,找不到class文件。
1368 0
ssh限制登录IP修改端口
在/etc/hosts.allow输入    (其中192.168.10.88是你要允许登陆ssh的ip,或者是一个网段192.168.10.0/24)    sshd:192.168.10.88:allow       在/etc/hosts.deny输入(表示除了上面允许的,其他的ip   都拒绝登陆ssh)    sshd:ALLvi /etc/ssh/sshd_config   比如说你只允许1.1.1.1这个IP进入,其它都禁止: 方法1、iptables。
475 0
Class 4 使用PolarDB和ECS搭建门户网站
Class 4 使用PolarDB和ECS搭建门户网站
187 0
无法解析类型 javax.servlet.http.HttpServletRequest。从必需的 .class 文件间接引用
java.lang.Error: 无法解析的编译问题: 无法解析类型 javax.servlet.http.HttpServletRequest。从必需的 .class 文件间接引用了它 无法解析类型 javax.servlet.http.HttpServletResponse。
1510 0
+关注
boxti
12535
10037
文章
1327
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载