Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
读取Java字节码指令:数字是什么意思?_Java_Bytecode - Fatal编程技术网

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

读取Java字节码指令:数字是什么意思?,java,bytecode,Java,Bytecode,我在阅读java字节码时看到: getfield #5 (Field java.lang.String name) #5是什么意思 如何用字节码编写程序?指令(IIRC)在类文件的常量池中引用关于应该查找哪个字段的信息。这里的#5表示“常量池条目编号5”,这个常量池包含这样的信息:“查找java.lang.String类型的字段name)。原因是它保持getfield指令的大小不变,而不管要查找的字段的名称或类型如何 我不确定我是否理解你所说的“如何用字节码编写程序?”这是一个相当开放的问题;

我在阅读java字节码时看到:

getfield #5 (Field java.lang.String name)
#5
是什么意思


如何用字节码编写程序?

指令(IIRC)在类文件的常量池中引用关于应该查找哪个字段的信息。这里的#5表示“常量池条目编号5”,这个常量池包含这样的信息:“查找
java.lang.String
类型的字段
name
)。原因是它保持
getfield
指令的大小不变,而不管要查找的字段的名称或类型如何

我不确定我是否理解你所说的“如何用字节码编写程序?”这是一个相当开放的问题;它类似于问如何用任何语言编写程序,需要大量的学习。你可能想研究Java汇编程序,它可以大大简化这一过程


希望这有帮助!

Java类文件和字节码

 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
Java类文件(字节码文件)由不同的组件组成:

  • 幻数:0xCAFEBABE
  • 类文件格式的版本:类文件的次要版本和主要版本
  • 常量池:类的常量池
  • (……)
  • 字段:类中的任何字段
  • 方法:类中的任何方法
  • 属性:类的任何属性(例如源文件的名称等)
数字#5只是指常量池中的一个位置。在该位置会找到一个常量_FieldRef,其中包含对常量_name和type的引用,以及对常量_name和type的引用(其中包含实际字符串/名称)

因此,流程如下所示:

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

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

手写字节码

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


它是常量池索引,常量池存储类文件的所有信息,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
字节码指令的格式为
指令常量池索引

  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是
//java/io/PrintStream.println:(Ljava/lang/String;)V

如果我们遵循常量池中的引用,我们会发现所有信息都存储在字符串中,并组合成复杂类型,如方法、字段、类


用Java编写并编译程序。您希望实现什么?类似ASM的JVM优化?