读取Java字节码指令:数字是什么意思?

时间:2012-02-17 21:33:18

标签: java bytecode

我正在阅读java字节码并看到了这个:

getfield #5 (Field java.lang.String name)

#5是什么意思?

如何用字节码编写程序?

3 个答案:

答案 0 :(得分:6)

Java类文件和字节码

Java类文件(字节码文件)由不同的组件组成:

http://en.wikipedia.org/wiki/Java_class_file

  • 幻数:0xCAFEBABE
  • 类文件格式的版本:类文件的次要版本和主要版本
  • 常量池:类的常量池
  • (...)
  • 字段:类中的任何字段
  • 方法:类中的任何方法
  • 属性:类的任何属性(例如源文件的名称等)

数字#5仅指恒定池中的位置。在该位置找到CONSTANT_FieldRef,其中包含对CONSTANT_NameAndType以及其他属性的引用。 CONSTANT_NameAndType包含对CONSTANT_Utf8的引用(包含实际的字符串/名称。)

所以流程看起来像这样:

getfield #number -> FieldRef -> NameAndType -> Utf8 -> string

http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html

因此,不是在每个getfield指令中保存整个字符串,而是保存一个数字。这样可以提高类文件中解释器(或JIT)和空间的性能。

手写字节码

可以使用此工具将手写字节码组装到类文件中(它包含大量示例):

http://jasmin.sourceforge.net/

答案 1 :(得分:4)

getfield指令(IIRC)引用类文件的常量池,以获取有关应查找哪个字段的信息。这里的#5表示“常量池条目号5”,然后此常量池包含“查找类型name的字段java.lang.String”的信息。原因是它保持大小无论要查找的字段的名称或类型如何,getfield指令都是相同的。

我不确定我是什么意思“我怎么能用字节码编写程序?”这是一个非常开放的问题;它类似于询问如何用任何语言编写程序,并且需要大量的学习。您可能希望查看Jasmin Java汇编程序,这可以大大简化此过程。

希望这有帮助!

答案 2 :(得分:0)

它是常量池索引,常量池存储类文件的所有信息,JVM指令使用索引来引用类信息,例如字段,方法。

我将使用hello world示例演示其工作原理:

来源

System.out.println("hello world");

字节码

 0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
 3: ldc           #3                  // String hello world
 5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
 8: return

字节码指令的格式为instruction constant pool index

  Constant pool:

   #4 = Methodref          #28.#29        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #28 = Class              #36            // java/io/PrintStream
  #29 = NameAndType        #37:#38        // println:(Ljava/lang/String;)V
  #36 = Utf8               java/io/PrintStream
  #37 = Utf8               println
  #38 = Utf8               (Ljava/lang/String;)V

所以该指令将调用索引为4的方法

invokevirtual #4

并且索引4是Methodref中的// java/io/PrintStream.println:(Ljava/lang/String;)V

如果我们遵循常量池中的引用,则会发现所有信息都存储在字符串中,并被堆肥为诸如方法,字段,类之类的复杂类型。