我正在阅读java字节码并看到了这个:
getfield #5 (Field java.lang.String name)
#5
是什么意思?
如何用字节码编写程序?
答案 0 :(得分:6)
Java类文件和字节码
Java类文件(字节码文件)由不同的组件组成:
http://en.wikipedia.org/wiki/Java_class_file
数字#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)和空间的性能。
手写字节码
可以使用此工具将手写字节码组装到类文件中(它包含大量示例):
答案 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
如果我们遵循常量池中的引用,则会发现所有信息都存储在字符串中,并被堆肥为诸如方法,字段,类之类的复杂类型。