java 字节码如何解读 java 字节码技术_怎么改变源码的特征码

前言

随着Java开发技术不断被推到新的高度,因此越来越需要具备对更深入的基础技术的理解,比如Java字节码相关。JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它其实可以理解为是一个虚构出来的计算机,是通过实际的计算机仿真模拟各种计算机功能来实现的。引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译,就可以在多种不同的平台上运行。而运行的就是本文要说的字节码。

字节码的探索

什么是Java字节码指令?简而言之,Java字节码指令就是Java虚拟机能够听得懂和可执行的指令,可以说是Java代码的最小执行单元,有点java基础的人一定都知道javac命令会将java源文件编译成字节码文件,其中就包含了大量的字节码指令。接下来用每个语言都有的灵魂例子(HelloWorld)做下说明,如下:

■java代码

public class HelloWorld {    public static void main(String[] args) {        System.out.println("HelloWorld");    }

}

■字节码

...  ...省略  public static void main(java.lang.String[]);    descriptor: ([Ljava/lang/String;)V    flags: ACC_PUBLIC, ACC_STATIC    Code:      stack=2, locals=1, args_size=1         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;         3: ldc           #3                  // String HelloWorld         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V         8: return      LineNumberTable:        line 3: 0        line 4: 8      LocalVariableTable:        Start  Length  Slot  Name   Signature            0       9     0  args   [Ljava/lang/String;}SourceFile: "HelloWorld.java"

可以看到短短几行java代码生成的字节码却比较的长,因篇幅有限,仅针对关键代码进行说明,以上stack指的是操作数栈,包含的就是字节码指令。LineNumberTable指的是描述java源代码行号与字节码行号之间的对应关系,LocalVariableTable指的是局部变量表中的变量和java源码的变量之间的关系。接下来介绍一下执行顺序,java源码相对比较简单,意思就是把HelloWorld这个英文单词打印到控制台显示出来。而字节码却是按部就班分成了4个指令依次执行,为便于理解,举一个射击子弹的例子结合以上的代码逐一对比说明:

1:获取一把手枪↓

// 加载打印对象入栈0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;

2:加载子弹入弹夹↓

// 加载常量池中的字符串入栈3: ldc           #3                  // String HelloWorld

3:执行击发动作↓

// 执行打印动作出栈5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V

4:放下枪,动作结束↓

// 返回栈顶结束8: return

经过上面这个例子,相信大家对整个字节码指令的执行,应该有了一个大概的认识,因为以上的例子相对比较简单,因此涉及到的字节码指令也只有以上4个,但是即使如此,也还是用到了加载指令和方法调用和返回指令,都是出现频率非常高的几大类字节码指令了。

字节码的思考

可能大家觉得相较于Java代码而言,字节码指令显得有点晦涩难懂,或者不太明白学习字节码指令的意义在哪里,人总是根据自己已经掌握的知识和技能来解决问题的,这里有个悖论,有时候你觉得有些技术没用恰恰是因为你没有熟练掌握它,遇到可以使用它的场景你根本想不到用。字节码指令可以从比源码更深的层面去学习 Java 相关知识虽然不可能所有问题都用字节码的知识来解决,但是它给你一个学习的途径。比如通过字节码的学习你可以更好地理解 Java中各种语法和语法糖背后的原理,更好地理解多态等语言特性。

最后附上字节码的脑图↓

java 字节码如何解读 java 字节码技术_怎么改变源码的特征码_02

结语

纵观技术发展,新的技术层出不穷,结构也越来越复杂,但是底层的结构确是不怎么有较大的调整的,比如字节码指令,如有好的基础,对较快理解和掌握新技术是非常有帮助的,鲸技术们一直在路上不断努力和追求着。