`
sslaowan
  • 浏览: 379672 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

用ASM为类动态增加属性

阅读更多

通过程序修改 .class 文件! 

下面这个是用 ASM 工具为 Student 类添加一个 public String 类型的 address 属性: 

1,需要添加属性的原始类:Student.java 

Java code
public class Student { private int age; private String name; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }



2,添加属性的适配器:AddFieldAdapter.java 

Java code
import org.objectweb.asm.ClassAdapter; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; public class AddFieldAdapter extends ClassAdapter { private int accessModifier; private String name; private String desc; private boolean isFieldPresent; public AddFieldAdapter(ClassVisitor cv, int accessModifier, String name, String desc) { super(cv); this.accessModifier = accessModifier; this.name = name; this.desc = desc; } @Override public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { if (name.equals(this.name)) { isFieldPresent = true; } return cv.visitField(access, name, desc, signature, value); } @Override public void visitEnd() { if (!isFieldPresent) { FieldVisitor fv = cv.visitField(accessModifier, name, desc, null, null); if (fv != null) { fv.visitEnd(); } } cv.visitEnd(); } }



3,添加属性的工具 AddField.java 

Java code
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import org.objectweb.asm.ClassAdapter; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; public class AddField { private Class clazz = null; private ClassReader cr = null; private ClassWriter cw = null; private ClassAdapter ca = null; private File classFile = null; private final static String CLASS_FILE_SUFFIX = ".class"; public AddField(Class clazz) { this.clazz = clazz; } /** * 添加一个 public 的类成员 * @param fieldName 类成员名 * @param fieldDesc 类成员类型描述 */ public void addPublicField(String fieldName, String fieldDesc) { if(cr == null) { try { cr = new ClassReader(clazz.getCanonicalName()); } catch (IOException e) { e.printStackTrace(); } cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); } if(ca == null) { ca = new AddFieldAdapter(cw, Opcodes.ACC_PUBLIC, fieldName, fieldDesc); } else { ca = new AddFieldAdapter(ca, Opcodes.ACC_PUBLIC, fieldName, fieldDesc); } } /** * 将字节码写入类的 .class 文件 * */ public void writeByteCode() { cr.accept(ca, ClassReader.SKIP_DEBUG); byte[] bys = cw.toByteArray(); OutputStream os = null; try { os = new FileOutputStream(getFile()); os.write(bys); } catch (IOException e) { e.printStackTrace(); } finally { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 获得类文件的 File 对象 * @return */ private File getFile() { if(classFile == null) { StringBuffer sb = new StringBuffer(); sb.append(clazz.getResource("/")) .append(clazz.getCanonicalName().replace(".", File.separator)) .append(CLASS_FILE_SUFFIX); classFile = new File(sb.substring(6)); } return classFile; } }



4,字节码处理:PreCompileProcess.java 

Java code
public class PreCompileProcess { public static void main(String[] args) { // 为 Student 添加字段 AddField add = new AddField(Student.class); // 添加一个名为 address,类型为 java.lang.String 的 public 字段 add.addPublicField("address", "Ljava/lang/String;"); // 再增加一个名为 tel,类型为 int 的 public 方法 add.addPublicField("tel", "I"); // 重新生成 .class 文件 add.writeByteCode(); } }



5,测试类:Test.java 

Java code
public class Test { public static void main(String[] args) { Student stu = new Student(); stu.setAge(10); stu.setName("Tom"); stu.address = "Beijing"; // 新增加的 address 字段 stu.tel = 56; // 新增加的 tel 字段 System.out.println("Name: " + stu.getName()); System.out.println("Age: " + stu.getAge()); System.out.println("Address: " + stu.address); System.out.println("Tel: " + stu.tel); } }


上面的代码需要 ASM 工具才能进行编译,ASM 可以到 http://asm.objectweb.org/ 上面去下载。 

执行顺序: 

javac Student.java 
javac -cp .;lib/asm-all-3.1.jar PreCompileProcess.java 
java -cp .;lib/asm-all-3.1.jar PreCompileProcess 
javac Test.java 
java Test 

在 Student.java 没有修改的情况下,PreCompileProcess 只需要执行一次就可以了。

分享到:
评论

相关推荐

    ASM维护使用指导手册

    本手册的目的是为IT专业人员提供ASM的维护和使用指南,帮助他们更好地理解和操作ASM实例,确保数据库系统的稳定运行。 2. **范围** 本手册适用于那些需要管理Oracle数据库环境中ASM实例的系统管理员和DBAs。内容...

    ASM官方文档

    ASM官方文档不仅为数据库管理员提供了一个关于ASM使用的全面指南,同时也从技术细节和管理实践角度,为数据库的存储优化和管理提供了理论和实践的参考。这些内容对于任何需要深入了解并实施Oracle ASM解决方案的专业...

    asm-attrs.jar.zip

    3. **属性处理**:ASM-Attrs.jar 提供了对类、字段、方法等属性的高级操作,包括访问、修改和添加自定义属性。在处理如注解、运行时可见性等元数据时,这一特性尤为重要。 4. **API设计**:ASM的API设计简洁而强大...

    logback日志级别动态切换的终极方案(Java ASM使用).doc

    总的来说,logback日志级别动态切换的终极方案(Java ASM使用)是针对大规模分布式系统的一种高效策略,能够在不重启服务的情况下实现日志级别的即时调整和过滤,降低了对业务开发团队的依赖。但同时,这也需要...

    asm-attrs-2.1.jar.zip

    例如,可以使用ASM来动态生成类,以实现动态代理,或者在运行时检查或修改类的方法体,以进行性能优化或调试。 总的来说,ASM是一个强大的工具,对于需要在运行时对Java字节码进行操作的开发者来说,它是不可或缺的...

    asm官方代码文档

    5. **动态代理**:ASM可以用来创建动态代理类,实现接口或扩展特定类。这在AOP(面向切面编程)或者测试框架中非常有用,可以快速生成代理对象以拦截方法调用。 6. **代码混淆**:ASM可用于代码混淆,通过对类名、...

    ASM操作加盘.7z

    8. **ASM磁盘组的扩展与收缩**:ASM磁盘组可以在运行时动态扩展,添加更多磁盘以增加存储空间。同样,如果需要减少存储,也可以在不影响服务的情况下,从磁盘组中安全地删除磁盘。 9. **ASM的备份与恢复**:ASM提供...

    asm-3.1.jar

    3. **字节码修改**:在解析类文件后,ASM允许开发者修改这些对象模型,比如添加、删除或修改方法体、字段和类属性。这种能力对于AOP(面向切面编程)和代码增强等场景非常有用。 4. **字节码生成器**:ASM提供了...

    asm-attrs-1.5.3.jar.zip

    总之,ASM-attrs-1.5.3.jar作为ASM库的一个版本,为Java开发者提供了强大的字节码操作能力,特别是对于处理类属性方面,使得我们可以创建更复杂、更灵活的程序。同时,了解和遵循相关的许可协议,是使用开源库的基本...

    C++汇编x64调用asm文件例子

    确保选择“x64”为目标平台,并添加汇编源文件到项目中。 通过这种方式,你可以在C++项目中直接集成和调用汇编代码,充分利用x64架构的性能优势。记住,虽然汇编语言能提供更高的控制和效率,但它也更难编写和维护...

    asm-tree-3.3.1.jar.zip

    首先,ASM是一个Java字节码操纵和分析框架,它可以直接用来动态生成类或者增强已有类的功能。ASM Tree库则是ASM框架中的一个模块,它的主要作用是将ASM低级别的字节码操作转化为直观的树形结构,便于开发者理解和...

    asm-all-3.3.1-sources.jar.zip

    2. **字节码分析**:ASM可以解析Java类的字节码,提供对类结构的详细访问,如类、接口、字段、方法、注解等,以及它们的属性。 3. **动态代理**:利用ASM,开发者可以创建动态代理类,实现特定的接口并在运行时拦截...

    asm-tree-2.1.jar.zip

    ASM是一个Java字节码操控和分析框架,它可以直接解析和生成Java类文件,而ASM Tree库则是ASM框架的一部分,它提供了将字节码转换为抽象语法树(AST)的能力,进而便于进行代码分析和修改。本文将详细介绍ASM Tree ...

    ORACLE 10g所需asm包

    4. **创建ASM磁盘组**: 使用ASM管理工具(如`asmca`或SQL命令)创建ASM磁盘组,指定磁盘、冗余级别和磁盘组属性。 5. **安装ASM实例**: 安装Oracle 10g软件时,选择创建ASM实例的选项,遵循安装向导完成配置。 6. **...

    Oracle 10.2 ASM 最佳实践 最终版本

    - **动态存储**:ASM支持动态增加或减少磁盘组中的物理磁盘数量,从而实现灵活的存储管理。 - **空间分配**:可以根据需要动态分配和回收空间,无需预先指定文件大小。 #### 重新平衡和重新分配 - **重新平衡**:...

    centos6 asm依赖包

    5. **创建ASM磁盘组**: 使用`asmca`工具或SQL命令来创建ASM磁盘组,分配空间并定义属性。 6. **配置数据库实例**: 在ASM上创建数据库实例,利用ASM的存储优势。 在配置过程中,注意遵循最佳实践,如定期备份OCR和...

    asm-attrs-2.0.jar.zip

    描述中提到的"asm, attrs, 2.0, jar.zip包下载, 依赖包"表明这个压缩文件与ASM库的Attributes模块有关,该模块可能处理Java类文件中的属性信息。"2.0"是ASM Attributes模块的版本号,通常每个新版本都会包含错误修复...

    大牛描绘整理的Oracle asm结构图不容错过

    ASM提供了一系列动态性能视图(Dynamic Performance Views, DPVs),用于查询ASM实例的状态和性能信息。例如: - `V$ASM_DISKGROUP`: 显示磁盘组的信息。 - `V$ASM_DISK`: 显示磁盘的信息。 - `V$ASM_OPERATION`: ...

    oracle ASM添加磁盘

    - **确认磁盘**: 再次使用 `listdisks` 命令确认新磁盘已经被正确识别并添加到 ASM 中。 #### 四、总结 在 AIX、HP-UX 和 Linux 操作系统环境下,向 Oracle ASM 添加新磁盘的过程主要包括:扫描映射到主机的新磁盘...

    vs2008搭建asm模板

    总结来说,使用VS2008搭建ASM模板的过程包括:创建空的Win32控制台应用项目,添加汇编源代码文件,设置文件类型为汇编,编写汇编代码,最后编译和调试。通过这种方式,我们可以充分利用VS2008的强大功能,高效地进行...

Global site tag (gtag.js) - Google Analytics