`
zhaohaolin
  • 浏览: 1011654 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

使用Javassist包操作class文件

    博客分类:
  • JAVA
阅读更多

下面这个类用来显示一个class文件中的内容,也可以调用相应类的方法修改其内容:

package classdump;

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import javassist.bytecode.*;
/**
*
* @author zj
*/
public class ClassDump {
    private String fileName;

    ClassFile cf;

    public ClassDump(String s) {
        fileName = s;
    }

    public void init() throws FileNotFoundException, IOException {
        cf = new ClassFile(new DataInputStream(new FileInputStream(fileName)));
    }

    /**
     * @return the fileName
     */
    public String getFileName() {
        return fileName;
    }

    public void printAll() {
        PrintStream out = System.out;

        pkvp(out, "minor_version", cf.getMinorVersion());
        pkvp(out, "major_version", cf.getMajorVersion());
        printConstPool(out);
        printAccessFlags(out);
        pkvp(out, "this_class", cf.getName());
        pkvp(out, "super_class", "[id:" + cf.getSuperclassId() + ",name:" + cf.getSuperclass() + "]");

        pkvp(out, "interfaces_count", cf.getInterfaces().length);
        for (int i=0;i<cf.getInterfaces().length;i++) {
            pkvp(out, "\tinterface" + i , cf.getInterfaces()[i]);
        }

        pkvp(out, "fields_count", cf.getFields().size());
        for (int i = 0; i < cf.getFields().size(); i++) {
            FieldInfo fi = (FieldInfo) cf.getFields().get(i);
            pkvp(out, "\tfield" + i, "[name:" + fi.getName() + "]");
        }

        pkvp(out, "methods_count", cf.getMethods().size());
        for(int i=0;i<cf.getMethods().size();i++) {
            MethodInfo mi = (MethodInfo)cf.getMethods().get(i);
            pkvp(out, "\tmethod" + i, "[name:" + mi.getName() + "]" );
        }

        pkvp(out, "attributes_count", cf.getAttributes().size());
        for(int i=0;i<cf.getAttributes().size();i++) {
            AttributeInfo ai = (AttributeInfo)cf.getAttributes().get(i);
            pkvp(out, "\tattribute" + i, "[name:" + ai.getName() + "]");
        }

    }

    private void printFields(PrintStream out) {
    }

    private void printAccessFlags(PrintStream out) {
        String s = "";
        int flags = cf.getAccessFlags();
        if ((flags & 0x0001)!=0) s += "public ";
        if ((flags & 0x0010)!=0) s += "final ";
        if ((flags & 0x0020)!=0) s += "super ";
        if ((flags & 0x0200)!=0) s += "interface ";
        if ((flags & 0x0400)!=0) s += "abstract ";
        pkvp(out, "access_flags", s);
    }

    private void printConstPool(PrintStream out) {
        pkvp(out, "constant_pool_count", cf.getConstPool().getSize());
        for (int i = 1; i < cf.getConstPool().getSize(); i++) {
            String tag = null;
            String value = null;
            switch (cf.getConstPool().getTag(i)) {
                case ConstPool.CONST_Class:
                    tag = "class";
                    value = cf.getConstPool().getClassInfo(i);
                    break;
                case ConstPool.CONST_Double:
                    tag = "double";
                    break;
                case ConstPool.CONST_Fieldref:
                    tag = "field reference";
                    value = "[name:" + cf.getConstPool().getFieldrefName(i) + ",type:" + cf.getConstPool().getFieldrefType(i) + ",class:" + cf.getConstPool().getFieldrefClassName(i) + "]";
                    break;
                case ConstPool.CONST_Float:
                    tag = "float";
                    break;
                case ConstPool.CONST_Integer:
                    tag = "integer";
                    value = Integer.toString(cf.getConstPool().getIntegerInfo(i));
                    break;
                case ConstPool.CONST_InterfaceMethodref:
                    tag = "interface method reference";
                    break;
                case ConstPool.CONST_Long:
                    tag = "long";
                    break;
                case ConstPool.CONST_Methodref:
                    tag = "method reference";
                    value = "[name:" + cf.getConstPool().getMethodrefName(i) + ",type:" + cf.getConstPool().getMethodrefType(i) + ",class:" + cf.getConstPool().getMethodrefClassName(i) + "]";
                    break;
                case ConstPool.CONST_NameAndType:
                    tag = "name and type";
                    value = cf.getConstPool().getNameAndTypeName(i) + ":" + cf.getConstPool().getNameAndTypeDescriptor(i);
                    break;
                case ConstPool.CONST_String:
                    tag = "string";
                    value = cf.getConstPool().getStringInfo(i);
                    break;
                case ConstPool.CONST_Utf8:
                    tag = "utf8";
                    value = cf.getConstPool().getUtf8Info(i);
                    break;
                default:
                    tag = Integer.toString(cf.getConstPool().getTag(i));
            }
            pkvp(out, "\tconst" + i + "(" + tag + ")", value);
        }
    }

    /**
     * Print Key Value Pair
     * @param out
     * @param key
     * @param value
     */
    private void pkvp(PrintStream out, String key, Object value) {
        out.println(key + "=" + value);
    }

    /**
     * @param fileName the fileName to set
     */
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

}

使用这个类的例子:

public class Main {
    public static void main(String[] args) {
        try {
            ClassDump cd = new ClassDump("d:\\Battle.class");
            cd.init();
            cd.printAll();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

分享到:
评论

相关推荐

    借助jclasslib与javassist修改java class字节码

    // 写入新的.class文件 ctClass.writeFile("D:\\java_proj\\com\\unmi\\HelloWorld_new.class"); } } ``` #### 五、总结 通过以上步骤,我们可以看到,即使没有源代码,也可以利用`jclasslib`和`javassist`这样...

    jboss-javassist和JByteMode整合包

    3. **字节码重新生成**:使用Javassist将修改后的源代码重新编译为字节码,并替换原有的.class文件。 4. **加载到JVM**:最后,将修改后的字节码加载到Java虚拟机,使修改生效。 **注意事项** 虽然这种动态字节码...

    javassist demo

    如果你需要将修改保存到磁盘,可以使用`toBytecode()`生成字节码,然后用`ClassFile`对象写入文件。 9. **异常处理**:Javaassist的API也支持添加、修改和删除异常处理代码。`CtMethod.addCatch()`方法可以添加新的...

    运用javassist和annotation修改class的特定method的class byte code

    4. **生成新的类文件**:最后,我们需要将修改后的字节码写回到磁盘,或者在内存中直接使用这个新版本的类。 ```java ctClass.writeFile(); // 写入磁盘 // 或者 Class&lt;?&gt; modifiedClass = ctClass.toClass(); // ...

    javassistDemo.zip

    - 保存或加载修改:修改完成后,可以使用`toClass()`方法将CtClass对象转换回实际的Java类,或者将其保存为新的.class文件。 这个"javassistDemo.zip"的示例可能涵盖了这些基本操作,并提供了具体的代码示例,帮助...

    Javassist学习手册

    - **生成类文件**: 使用 `CtClass.writeFile()` 方法将修改后的类写回到磁盘上的 `.class` 文件中。 - **加载为 Java 类**: 使用 `CtClass.toClass()` 方法可以将 `CtClass` 对象加载成 Java 类 (`java.lang.Class`...

    javassist 包

    1. 字节码操作:Javaassist通过读取 `.class` 文件或字节码流来创建和修改类。它提供了一系列的API,如 `ClassPool`、` CtClass` 和 ` CtMethod` 等,这些API可以用来解析和构建字节码。例如,`CtClass` 对象代表一...

    修改.class文件.zip

    一个常见的库用于操作.class文件的是“jasmin”或“javassist”。在这里,我们将使用Java编程语言来实现。假设你已经有了一个名为`Main.java`的文件,它包含了一个名为`modifyClassFile`的函数,用于根据编号修改....

    javassist-3.18.0-GA

    4. **使用javassist修改class文件.txt**: 这个文件可能是一个示例或教程,解释了如何利用 Javaassist 修改已存在的 `.class` 文件。通过读取这个文件,开发者可以学习到如何在运行时改变类的行为,例如添加新的...

    jclasslib反编译工具包,修改class文件

    jclasslib就是这样一款强大的反编译工具,它允许开发者查看和修改Java的Class文件,为我们的编程工作提供了极大的便利。本文将详细介绍jclasslib工具包的使用及其在JavaEE、移动开发,尤其是安卓开发中的应用。 ...

    java 反编译工具 jboss-javassist

    在使用Javassist时,开发者通常会先引入对应的jar包,例如压缩包中的"jbosss-javassist-javassist-dfd0733"。这个文件很可能是Javassist的一个特定版本,包含必要的类库和可能的示例代码。要开始使用,可以按照以下...

    Java下的Class代码查看器+修改器

    Java下的Class代码查看器与修改器是用于深入理解与操作Java字节码的重要工具,它们可以帮助开发者查看并可能修改已编译的Java类文件(即.class文件),这对于调试、逆向工程、性能优化以及理解Java运行时机制具有...

    通过自定义Gradle插件修改编译后的class文件

    下面是一个简单的自定义Gradle插件示例,展示了如何使用ByteBuddy修改编译后的class文件: 1. 创建一个新的Gradle插件项目,包含以下目录结构: ``` my-plugin/ ├── src/main/groovy │ └── ...

    javassist18,20,22三个版本.zip

    它通过解析.class文件为用户提供了类的表示,并提供了API来操作这些类。 2. **版本差异**: - **javassist-3.18.0-ga**:这是较早的一个版本,可能包含了基本的功能,如类的加载、修改和保存。此版本可能对某些...

    扫描Class文件的方法

    1. **递归文件系统扫描**:遍历指定目录下的所有文件,通过文件名判断是否为Class文件,然后使用`Class.forName()`或`ClassLoader.loadClass()`加载并检查。 2. **使用ClassLoader资源流**:通过`ClassLoader.get...

    JVM之用Java解析class文件共10页.pdf.zi

    本文将深入探讨JVM如何通过Java解析class文件,揭示其内部工作原理,以及如何实现这一过程。我们主要关注的是标题所提及的"JVM之用Java解析class文件"这一主题,这涉及到Java程序编译后的二进制表示以及JVM的类加载...

    javassist-3.18.2-GA.jar

    8. **ClassFile** 和 **ConstPool**:这两个类分别代表 Class 文件结构和常量池,提供了对 Java 类文件底层结构的访问。 在实际应用中,Javaassist 常用于 AOP(面向切面编程)、动态代理、性能监控、测试工具和...

    修改javaclass工具包

    这些工具允许我们直接操作字节码指令,实现对`.class`文件的精确修改。 4. **ASM、Javassist库**:这些是更底层的字节码操作库,提供了API来动态生成和修改字节码。ASM库非常底层且灵活,适合专业级的字节码操作;...

    javassist-3.11

    2. **字节码解析**:Javassist能够解析.class文件,并将其转换为可操作的CtClass对象。这使得开发者可以在运行时对类进行分析和修改,而无需重新编译源代码。例如,你可以使用`ClassPool.getClass()`来获取已加载类...

    javassist-3.9.0.GA.jar.zip

    这个"javassist-3.9.0.GA.jar.zip"文件包含了Javaassist库的版本3.9.0 GA,这是一个归档(JAR)文件,通常用于分发Java类库。 Javaassist的核心概念是它允许开发者在运行时分析、修改和生成Java类。这对于实现诸如...

Global site tag (gtag.js) - Google Analytics