fbpx
维基百科

Java字节码

Java 字节码(英語:Java bytecode)是Java虚拟机执行的一种指令格式。大多数操作码英语Opcode都是一个字节长,而有些操作需要参数,导致了有一些多字节的操作码。而且并不是所有可能的256个操作码都被使用;其中有51个操作码被保留做将来使用。除此之外,原始Java平台开发商,昇陽微系统,额外保留了3个代码永久不使用。

与Java的关系 编辑

一个Java程序员并不需要理解所有的Java字节码。但是,就像IBM developerWorks周刊建议的那样:“理解字节码以及理解Java编译器如何生成Java字节码与学习汇编知识对于C/C++程序员有一样的意义。”[1]

指令 编辑

指令码为一个字节,有256个可能的代码值(28=256),因此一个字节的指令码最多可能有256种不同的操作。其中,0x00、0xFE、0xCA、0xFF被指定保留。例如0xCA作为一个Java调试器的中断指令而从未被语言使用。相似地,0xFE和0xFF也未被语言使用[2]

指令可以基本分为以下几类:

  • 存储指令 (例如:aload_0,istore)
  • 算术与逻辑指令 (例如: ladd,fcmpl)
  • 类型转换指令 (例如:i2b,d2i)
  • 对象创建与操作指令 (例如:new,putfield)
  • 堆栈操作指令 (例如:swap,dup2)
  • 控制转移指令 (例如:ifeq,goto)
  • 方法调用与返回指令 (例如:invokespecial,areturn)

除此之外,还有一些更特殊的指令,作为异常抛出或同步等作用。

大多数的指令有前缀和(或)后缀来表明其操作数的类型。如下表

例如,"iadd"指令将两个整数相加;而"dadd"指令将两个double浮点数相加。

"const"、 "load"、 "store"等涉及存储命令还会使用"_n"后缀,其中 "load"和"store"命令中的n可以为0到3之间的整数;而"const"命令中的n由类型指定。"const"指令把一个指定类型的值放入堆栈。例如"iconst_5"指令将一个整数5放入堆栈;而"dconst_1"将一个双精度浮点数1放入堆栈。"aconst_null"指令是放入一个null进堆栈。而对于"load" "store"指令中的n,指定了变量表中的存储位置。"aload_0"指令把在变量0中的对象(通常是"this"对象)放入堆栈,"istore_1"指令把栈顶的一个整数放入变量1。对于更高的变量,后缀将被去除,而这条指令将需要操作数。

计算模型 编辑

Java字节码的计算模型是面向堆栈结构计算机的。例如,一个x86处理器的汇编代码如下

mov eax, byte [ebp-4] mov edx, byte [ebp-8] add eax, edx mov ecx, eax 

这段代码将两个数值相加,并存入另一个地址。相似的反汇编字节码如下

0 iload_1 1 iload_2 2 iadd 3 istore_3 

在这里,需要相加的两个操作数被放入堆栈,而相加操作就在栈中进行,其结果也被放入堆栈。存储指令之后把栈顶的数据放入一个变量地址。在每条指令前面的数字仅仅是表示这条指令到方法开始处的偏移值。这种堆栈结构也可以推广到面向对象模型上。例如,有一个"getName"方法如下

 Method java.lang.String getName()  0 aload_0 // "this"对象被存入变量0  1 getfield #5 <Field java.lang.String name>  // 这个指令从栈顶取出一个对象,并从中搜索一个指定的域  // 并将相应的数据存入栈顶。  // 这个例子中,"name"域对应于该类中的第五个常量。    4 areturn // 返回栈顶的对象作为函数的返回值 

例子 编辑

考虑如下Java代码

 outer:  for (int i = 2; i < 1000; i++) {  for (int j = 2; j < i; j++) {  if (i % j == 0)  continue outer;  }  System.out.println (i);  } 

假设上述代码位于一个函数中,Java编译器可能将代码翻译成下述的Java字节码。

 0: iconst_2  1: istore_1  2: iload_1  3: sipush 1000  6: if_icmpge 44  9: iconst_2  10: istore_2  11: iload_2  12: iload_1  13: if_icmpge 31  16: iload_1  17: iload_2  18: irem  19: ifne 25  22: goto 38  25: iinc 2, 1  28: goto 11  31: getstatic #84; //Field java/lang/System.out:Ljava/io/PrintStream;  34: iload_1  35: invokevirtual #85; //Method java/io/PrintStream.println:(I)V  38: iinc 1, 1  41: goto 2  44: return 

基于Java字节码的语言 编辑

最常用的基于Java字节码的语言就是开发出Java字节码的Java语言。刚开始,只存在一个由昇陽微系统开发的一个编译器javac。而现在Java字节码规范已经可以得到,因此,第三方公司亦开发出支持Java字节码的编译器。例如:

  • Jikes,编译Java源代码到Java字节码(由IBM开发,用C++实现)
  • Espresso,编译Java源代码到Java字节码(仅支持Java 1.0)
  • GCJGNU Compiler for Java,编译Java代码到Java字节码;亦可以编译到机器代码。作为GNU Compiler Collection (GCC)的一部分提供。

有一些项目提供Java汇编器以便于直接用Java字节码进行开发。主要的Java汇编器如下:

  • Jasmin,读取Java类的文字描述;用一种简单的使用Java虚拟机指令的类汇编语法,输出Java类文件 [3]
  • Jamaica, 一种为Java虚拟机编写的宏汇编语言。其中,类与接口由Java语法定义,而其中的方法却由Java字节码定义。[4]

还有其他的一些编译器,对于其他语言生成Java字节码,使其可以运行在Java虚拟机之上。

运行 编辑

当前已经有很多种Java虚拟机产品,包括了自由软件和商业软件。 如果在Java虚拟机之中执行Java字节码并不理想,则可以使用一些工具例如GNU Compiler for Java将Java代码或Java字节码编译成机器码并由硬件直接运行。 而有一些处理器可以直接运行Java字节码,这种处理器名为Java处理器。

对动态语言的支持 编辑

Java虚拟机对动态类型语言提供了一定的支持。但绝大多数的Java虚拟机指令集是基于静态类型语言的。在静态类型机制下,方法调用中的类型分析都是在编译时执行的,而且缺乏一种机制在运行时确定一个类型已经确定相应的方法。

JSR292[5]中,在Java虚拟机层次增加了一种支持动态类型的指令invokedynamic,以支持在动态类型检测中的方法调用。 达芬奇机器英语Da Vinci Machine则是一种支持这种动态类型调用的虚拟机。 而所有支持JSE 7的Java虚拟机都应支持invokedynamic操作码。

参考文献 编辑

  1. ^ Understanding bytecode makes you a better programmer. [2014-01-28]. (原始内容于2008-12-08). 
  2. ^ 存档副本. [2014-01-28]. (原始内容于2013-02-21). 
  3. ^ . [2020-06-21]. (原始内容存档于2020-04-17). 
  4. ^ . [2014-01-28]. (原始内容存档于2012-06-24). 
  5. ^ see JSR 292. [2014-01-28]. (原始内容于2020-12-20). 

java字节码, java, 字节码, 英語, java, bytecode, 是java虚拟机执行的一种指令格式, 大多数操作码, 英语, opcode, 都是一个字节长, 而有些操作需要参数, 导致了有一些多字节的操作码, 而且并不是所有可能的256个操作码都被使用, 其中有51个操作码被保留做将来使用, 除此之外, 原始java平台开发商, 昇陽微系统, 额外保留了3个代码永久不使用, 目录, 与java的关系, 指令, 计算模型, 例子, 基于的语言, 运行, 对动态语言的支持, 参考文献与java的关系,. Java 字节码 英語 Java bytecode 是Java虚拟机执行的一种指令格式 大多数操作码 英语 Opcode 都是一个字节长 而有些操作需要参数 导致了有一些多字节的操作码 而且并不是所有可能的256个操作码都被使用 其中有51个操作码被保留做将来使用 除此之外 原始Java平台开发商 昇陽微系统 额外保留了3个代码永久不使用 目录 1 与Java的关系 2 指令 3 计算模型 4 例子 5 基于Java字节码的语言 6 运行 7 对动态语言的支持 8 参考文献与Java的关系 编辑一个Java程序员并不需要理解所有的Java字节码 但是 就像IBM developerWorks周刊建议的那样 理解字节码以及理解Java编译器如何生成Java字节码与学习汇编知识对于C C 程序员有一样的意义 1 指令 编辑指令码为一个字节 有256个可能的代码值 28 256 因此一个字节的指令码最多可能有256种不同的操作 其中 0x00 0xFE 0xCA 0xFF被指定保留 例如0xCA作为一个Java调试器的中断指令而从未被语言使用 相似地 0xFE和0xFF也未被语言使用 2 指令可以基本分为以下几类 存储指令 例如 aload 0 istore 算术与逻辑指令 例如 ladd fcmpl 类型转换指令 例如 i2b d2i 对象创建与操作指令 例如 new putfield 堆栈操作指令 例如 swap dup2 控制转移指令 例如 ifeq goto 方法调用与返回指令 例如 invokespecial areturn 除此之外 还有一些更特殊的指令 作为异常抛出或同步等作用 大多数的指令有前缀和 或 后缀来表明其操作数的类型 如下表 前 后缀 操作数类型i 整数l 长整数s 短整数b 字节c 字符f 单精度浮点数d 双精度浮点数z 布尔值a 引用例如 iadd 指令将两个整数相加 而 dadd 指令将两个double浮点数相加 const load store 等涉及存储命令还会使用 n 后缀 其中 load 和 store 命令中的n可以为0到3之间的整数 而 const 命令中的n由类型指定 const 指令把一个指定类型的值放入堆栈 例如 iconst 5 指令将一个整数5放入堆栈 而 dconst 1 将一个双精度浮点数1放入堆栈 aconst null 指令是放入一个null进堆栈 而对于 load store 指令中的n 指定了变量表中的存储位置 aload 0 指令把在变量0中的对象 通常是 this 对象 放入堆栈 istore 1 指令把栈顶的一个整数放入变量1 对于更高的变量 后缀将被去除 而这条指令将需要操作数 计算模型 编辑Java字节码的计算模型是面向堆栈结构计算机的 例如 一个x86处理器的汇编代码如下 mov eax byte ebp 4 mov edx byte ebp 8 add eax edx mov ecx eax 这段代码将两个数值相加 并存入另一个地址 相似的反汇编字节码如下 0 iload 1 1 iload 2 2 iadd 3 istore 3 在这里 需要相加的两个操作数被放入堆栈 而相加操作就在栈中进行 其结果也被放入堆栈 存储指令之后把栈顶的数据放入一个变量地址 在每条指令前面的数字仅仅是表示这条指令到方法开始处的偏移值 这种堆栈结构也可以推广到面向对象模型上 例如 有一个 getName 方法如下 Method java lang String getName 0 aload 0 this 对象被存入变量0 1 getfield 5 lt Field java lang String name gt 这个指令从栈顶取出一个对象 并从中搜索一个指定的域 并将相应的数据存入栈顶 这个例子中 name 域对应于该类中的第五个常量 4 areturn 返回栈顶的对象作为函数的返回值例子 编辑考虑如下Java代码 outer for int i 2 i lt 1000 i for int j 2 j lt i j if i j 0 continue outer System out println i 假设上述代码位于一个函数中 Java编译器可能将代码翻译成下述的Java字节码 0 iconst 2 1 istore 1 2 iload 1 3 sipush 1000 6 if icmpge 44 9 iconst 2 10 istore 2 11 iload 2 12 iload 1 13 if icmpge 31 16 iload 1 17 iload 2 18 irem 19 ifne 25 22 goto 38 25 iinc 2 1 28 goto 11 31 getstatic 84 Field java lang System out Ljava io PrintStream 34 iload 1 35 invokevirtual 85 Method java io PrintStream println I V 38 iinc 1 1 41 goto 2 44 return基于Java字节码的语言 编辑最常用的基于Java字节码的语言就是开发出Java字节码的Java语言 刚开始 只存在一个由昇陽微系统开发的一个编译器javac 而现在Java字节码规范已经可以得到 因此 第三方公司亦开发出支持Java字节码的编译器 例如 Jikes 编译Java源代码到Java字节码 由IBM开发 用C 实现 Espresso 编译Java源代码到Java字节码 仅支持Java 1 0 GCJ GNU Compiler for Java 编译Java代码到Java字节码 亦可以编译到机器代码 作为GNU Compiler Collection GCC 的一部分提供 有一些项目提供Java汇编器以便于直接用Java字节码进行开发 主要的Java汇编器如下 Jasmin 读取Java类的文字描述 用一种简单的使用Java虚拟机指令的类汇编语法 输出Java类文件 3 Jamaica 一种为Java虚拟机编写的宏汇编语言 其中 类与接口由Java语法定义 而其中的方法却由Java字节码定义 4 还有其他的一些编译器 对于其他语言生成Java字节码 使其可以运行在Java虚拟机之上 ColdFusion JRuby和Jython 两种基于Ruby和Python的脚本语言 Groovy 一种基于Java的脚本语言 Scala 一种类型安全的通用编程语言 支持面向对象编程和函数式编程 JGNAT和AppleMagic 编译Ada语言到Java字节码 Clojure 一种函数式的通用编程语言 提供优秀的并发性 是一种LISP方言 MIDletPascal JavaFX Script 由昇陽微系统公司开发的一种脚本语言 运行于Java虚拟机之上运行 编辑当前已经有很多种Java虚拟机产品 包括了自由软件和商业软件 如果在Java虚拟机之中执行Java字节码并不理想 则可以使用一些工具例如GNU Compiler for Java将Java代码或Java字节码编译成机器码并由硬件直接运行 而有一些处理器可以直接运行Java字节码 这种处理器名为Java处理器 对动态语言的支持 编辑Java虚拟机对动态类型语言提供了一定的支持 但绝大多数的Java虚拟机指令集是基于静态类型语言的 在静态类型机制下 方法调用中的类型分析都是在编译时执行的 而且缺乏一种机制在运行时确定一个类型已经确定相应的方法 JSR292 5 中 在Java虚拟机层次增加了一种支持动态类型的指令invokedynamic 以支持在动态类型检测中的方法调用 达芬奇机器 英语 Da Vinci Machine 则是一种支持这种动态类型调用的虚拟机 而所有支持JSE 7的Java虚拟机都应支持invokedynamic操作码 参考文献 编辑 Understanding bytecode makes you a better programmer 2014 01 28 原始内容存档于2008 12 08 存档副本 2014 01 28 原始内容存档于2013 02 21 Jasmin Home Page 2020 06 21 原始内容存档于2020 04 17 Jamaica The Java Virtual Machine JVM Macro Assembler 2014 01 28 原始内容存档于2012 06 24 see JSR 292 2014 01 28 原始内容存档于2020 12 20 取自 https zh wikipedia org w index php title Java字节码 amp oldid 79776086, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。