用BCEL设计字节码

这个最接近之前提出的API转换问题

这个需要扫描源代码找到此类的方法调用处,然后在方法调用处的前后添加指令

即将代码转换成如下形式:

public class StringBuilder
{
     public String buildString(int length) {
         String result = "";
         for (int i = 0; i < length; i++) {
             result += (char)(i%26 + 'a');
         }
         return result;
     }

     public static void main(String[] argv) {
         StringBuilder inst = new StringBuilder();
         for (int i = 0; i < argv.length; i++) {

             long start = System.currentTimeMillis();
             String result = inst.buildString(Integer.parseInt(argv[i]));
             System.out.println("Call to buildString$impl took " +
                     (System.currentTimeMillis()-start) + " ms.");

             System.out.println("Constructed string of length " +
                 result.length());
         }
     }
}

转换代码如下:

先扫描这个类中的各个方法

我准备改变一下生成策略,不自己写指令了,这个自己写指令比较麻烦,但要加的代码比较多时比较容易出错,当所加的代码有if,跳转语句,自己根本就不会如何写添哪些指令,这种写类似汇编指令总是很麻烦的。

先要把加的代码自己在某个类中事先用方法写好,实例方法也好,静态方法也好,方法带有参数或者有返回值,

这些参数和返回值供调用方法中的局部变量来替换和使用。

再要添加代码的方法的前后调用这些已经写好的方法的字节码的指令序列生成InstructionList,然后再添加到使用这个方法的指令序列中

如下

public class ToolUtil {

     public static long printStart() {
         System.out.println("start start start start");
         long start = System.currentTimeMillis();
         return start;
     }

     public static void printEnd(String methodname,long start){

         System.out.println("Call to "+methodname+" took " +
                 (System.currentTimeMillis()-start) + " ms.");
         System.out.println("end end end end end end");
     }
}

时间: 2025-01-20 15:15:18

用BCEL设计字节码的相关文章

Java编程的动态性,第7部分: 用BCEL设计字节码

Apache Byte Code Engineering Library (BCEL)可以深入 Java 类的字节码.可以用它 转换现有的类表示或者构建新的类,因为 BCEL 在单独的 JVM 指令级别上进行操作,所以可 以让您对代码有最强大的控制.不过,这种能力的代价是复杂性.在本文中,Java 顾问 Dennis Sosnoski 介绍了 BCEL 的基本内容,并引导读者完成一个示例 BCEL 应用程序,这 样您就可以自己决定是否值得以这种复杂性来换取这种能力. 在本系列的最后三篇文章中,我

JVM Class字节码之三-使用BCEL改变类属性

使用BCEL动态改变Class内容 之前对Class文件中的常量池,Method的字节码指令进行了说明.JVM Class详解之一JVM Class详解之二 Method字节码指令 现在我们开始实际动手,使用BCEL改变字节码指令,对Class文件进行功能扩充. 先介绍下BCEL全程Apache Byte Code Engineering Library,BCEL 每项内容操作在JVM汇编语言的级别 HelloWorld搞起 这个case我们需要给Programmer类做功能扩展,Program

V8 Ignition:JS 引擎与字节码的不解之缘

ARE WE FAST YET? 网站测试并展示了数个 JavaScript 引擎的性能数据,是各家 JS 引擎性能的比武场: 我们看到在这个比武场上,最近 Chrome 出现了多个新条目,其中很多条目都是关于 v8 的 Ignition 新架构的组合,他们是 v8 引擎最近推出的 JS 字节码解释器. 纵览各个 JS 引擎的实现,我们发现基于字节码的实现是主流.例如苹果公司的 JavaScriptCore (JSC) 引擎,2008 年时他们引入了 SquirrelFish(市场名 Nitro

Java字节码(.class文件)格式详解(一)

小介:去年在读<深入解析JVM>的时候写的,记得当时还想着用自己的代码解析字节码的,最后只完成了一部分.现在都不知道还有没有保留着,貌似Apache有现成的BCEL工程可以做这件事.当时也只是为了学习.这份资料主要参考<深入解析JVM>和<Java虚拟机规范>貌似是1.2版本的,整理出来的.里面包含了一些自己的理解和用实际代码的测试.有兴趣的童鞋可以研究研究.嘿嘿.要有错误也希望能为小弟指点出来,感激不尽.:) 1.总体格式 Class File format type

深入字节码 -- 计算方法执行时间

什么是字节码? java程序通过javac编译之后生成文件.class就是字节码集合,正是有这样一种中间码(字节码),使得scala/groovy/clojure等函数语言只用实现一个编译器即可运行在JVM上. 看看一段简单代码. public long getExclusiveTime() { long startTime = System.currentTimeMillis(); System.out.printf("exclusive code"); long endTime =

字节码及ASM使用

字节码及ASM使用 什么是字节码? 机器码 机器码(machine code)是CPU可直接解读的指令.机器码与硬件等有关,不同的CPU架构支持的硬件码也不相同. 字节码 字节码(bytecode)是一种包含执行程序.由一序列 op 代码/数据对 组成的二进制文件.字节码是一种中间码,它比机器码更抽象,需要直译器转译后才能成为机器码的中间代码.通常情况下它是已经经过编译,但与特定机器码无关.字节码主要为了实现特定软件运行和软件环境.与硬件环境无关. 字节码的实现方式是通过编译器和虚拟机器.编译器

Java字节码(.class文件)格式详解(二)

2.9   methods methods数组记录了类或接口中的所有方法,包括实例方法.静态方法.实例初始化方法和类初始化方法,但不包括父类或父接口中定义的方法.methods数组中每项都是method_info类型值,它描述了方法的详细信息,如名称.描述符.方法中的attribute(如Code Attribute记录了方法的字节码)等. method_info type descriptor remark u2 access_flags 记录方法的访问权限.见2.9.1 u2 name_in

Java字节码(.class文件)的代码解析

Java二进制指令代码以以下格式紧凑排列(opcode占一个字节): opcode operand* 除了tableswitch和lookupswitch两条指令中间存在填充字节以外,其他指令都没有填充字节,即使在两条指令之间也没有.因而在读取指令的时候,要根据指令的定义读取.  通过对上面Java指令集的分析可以知道,Java指令集中很大一部分没有操作数,因而对这部分指令,只需要读取一个字节的操作码,将操作码映射成助记符即可.  而对其他带操作数的指令,则需要根据不同类型分析(由于apache

JVM层对jar包字节码加密

github https://github.com/sea-boat/ByteCodeEncrypt 需求 拿到的需求是要对某特定的jar包实现加密保护,jar包需要提供给外部使用,但核心逻辑部分需要保护以免被简单反编译即能看到. 几个思路 大致想到以下几种方式: 1. 混淆器,将jar包混淆后反编译出来的东西看起来就很眼花,但如果耐心一点也是可以看出来的. 2. 对jar包进行加密,然后在Java层重写类加载器对其进行解密,以达到对jar包的加密保护.包括用对称加密算法和非对称加密算法.不管用