常量池

  在堆中的每个类都有一个与之相关的常量池。由于常量池不会改变,它们通常在编译的时候创建,常量池中的项对特定类中的任何方法中用到的(常量)名称进行编码。这类里包含出现常量的个数,以及指定一连串特定常量在类描述里的偏移量。

  所有的常量相关信息遵循基于常量类型的特定格式。例如:类级别的常量通常用于表示一个类或一个接口,并且拥有如下的格式:

CONSTANT_Class_info
{
    u1   tag;
    u2 name_index;
}

  其中tag是常量类的值, name_index是类的名称. int[][]的类名称是[[I. Thread[]的类名称是[Ljava.lang.Thread;.

  方法(代码)区

  Java 的方法区类似于其它编程语言运行时环境中的编译后的代码区域。他存储与编译后的代码中的方法相关的字节码指令,以及需要用于动态链接的执行环境符号表。任何调试信息以及可能需要的方法有关的其它信息也存储在这个区域。

  字节码指令集

  尽管程序员更喜欢用高级格式写代码,我们的电脑不能直接执行这些代码,这是我们为什么要在Java程序运行之前对其进行编译的愿意。一般来说,编译代码并不是机器可读的代码(机器代码)格式,也不是一种中级格式的代码,如:汇编语言或Java字节码。

  Java虚拟机所用的字节码指令类似于汇编指令。如果你曾经用过汇编语言,你知道指令集为了更高的效率将自身分解到小限度,对于在屏幕上输出之类的任务,要通过使用一系列的指令来完成。例如,Java语言允许我们只用一行指令能在屏幕上进行输出,像代码:

System.out.println("Hello world!");

  在编译的时候,Java编译器将这行输入语句转换成以下的字节码:

0 getstatic #6 <Field java.lang.System.out Ljava/io/PrintStream;>
3 ldc #1 <String "Hello world!">
5 invokevirtual #7 <Method java.io.PrintStream.println(Ljava/lang/String;)V>
8 return

  Java开发工具包(JDK)提供一种叫Java类文件反编译程序的查验字节码的工具。我们可以在命令行中输入javap命令来执行反编译。

  由于字节码指令时基于一种低级(语言)格式的,我们的程序执行速度接近于程序被编译成机器语言的执行速度。所有的机器指令都用一系列的0和1表示。在低级语言中,0和1的系列被一些合适的助记符代替,如字节码指令isub。类似于汇编语言,字节码指令的基本格式是:

<operation>   <operands(s)>

  因此,字节码指令集中的指令时有1字节的指定了要执行的操作的操作码,和操作所需要0个或者多个参数或数据组成。

  总结

  Java虚拟机只存在于我们电脑的内存之中。在电脑的内存中再创造一个设备需要七大关键组成:一系列寄存器、一个栈(stack)、一个执行环境、一个垃圾回收堆、一个常量池、一个方法存储区和一种将它们联系起来的机制。这种机制是字节码指令集。

  为了调查字节码,我们用java的class文件进行反编译。通过详细调查字节码指令,我们获取了关于Java虚拟机内部工作(原理)和Java本身的有价值见解。每个字节码指令执行一个特定范围的有限功能,例如:将一个对象压入栈中或从栈中取出一个对象。这些基本功能的组合表述了Java编程语言中定义的复杂的高级语句。这样看起来很棒,有些时候许多字节码指令只是为了实现一个简单Java语句操作。当我们应用这些字节码指令与Java虚拟机的七大组成时,Java获得了它的平台无关性并成为了世界上强大和通用的编程语言。