沙箱安全机制
上文中提到的java.lang.String就是沙箱安全机制的表现,保证了对java核心源代码的保护。
首先来看一下百度百科的定义:
在计算机科学中, 字面量(literal)是用于表达源代码中一个固定值的表示法(notation)。几乎所有计算机编程语言都具有对基本值的字面量表示, 诸如: 整数, 浮点数以及字符串; 而有很多也对布尔类型和字符类型的值也支持字面量表示; 还有一些甚至对枚举类型的元素以及像数组, 记录和对象等复合类型的值也支持字面量表示法.
这段话不太好理解,我们来拆解下(注意下面这段话纯属个人理解):
“字面量(literal)是用于表达源代码中一个固定值的表示法(notation)”,这里说明了两点:第一,字面量是体现在源码中的;第二,字面量是对一个固定值的表示。接下来它提到了“几乎所有计算机编程语言都具有对基本值的字面量表示”,并以一些基本数据类型、枚举、数组等数据类型举例。它们都有一个特点,就是它们的赋值是可以做到“代码可视化的”。你可以在代码中给以上提到的类型进行赋值。而我们赋值时所给出的“值”,更准确来说是一种“表示”(比如给数组赋值时,约定了需要用大括号括起来)就是字面量的含义。
举个例子:
同样,先来看一下书面定义:
符号引用:符号引用以一组符号来描述所引用的目标,符号引用可以是任何形式的字面量,只要使用时能够无歧义的定位到目标即可。比如org.simple.People类引用了org.simple.Language类,在编译时People类并不知道Language类的实际内存地址,因此只能使用符号org.simple.Language(假设是这个,当然实际中是由类似于CONSTANT_Class_info的常量来表示的)来表示Language类的地址。各种虚拟机实现的内存布局可能有所不同,但是它们能接受的符号引用都是一致的,因为符号引用的字面量形式明确定义在Java虚拟机规范的Class文件格式中。
直接引用: 直接引用可以是
(1)直接指向目标的指针(比如,指向“类型”【Class对象】、类变量、类方法的直接引用可能是指向方法区的指针)
(2)相对偏移量(比如,指向实例变量、实例方法的直接引用都是偏移量)
(3)一个能间接定位到目标的句柄
直接引用是和虚拟机的布局相关的,同一个符号引用在不同的虚拟机实例上翻译出来的直接引用一般不会相同。如果有了直接引用,那引用的目标必定已经被加载入内存中了。
说实话看这种书面化语言抽象晦涩,下面给出一些自己的理解吧。首先找到一个.class文件(来源:玩命学JVM(一))反编译后的结果中常量池的部分:
Constant pool: #1 = Methodref #6.#15 // java/lang/Object."<init>":()V #2 = Fieldref #16.#17 // java/lang/System.out:Ljava/io/PrintStream; #3 = String #18 // Hello World #4 = Methodref #19.#20 // java/io/PrintStream.println:(Ljava/lang/String;)V #5 = Class #21 // Main #6 = Class #22 // java/lang/Object #7 = Utf8 <init> #8 = Utf8 ()V #9 = Utf8 Code #10 = Utf8 LineNumberTable #11 = Utf8 main #12 = Utf8 ([Ljava/lang/String;)V #13 = Utf8 SourceFile #14 = Utf8 Main.java #15 = NameAndType #7:#8 // "<init>":()V #16 = Class #23 // java/lang/System #17 = NameAndType #24:#25 // out:Ljava/io/PrintStream; #18 = Utf8 Hello World #19 = Class #26 // java/io/PrintStream #20 = NameAndType #27:#28 // println:(Ljava/lang/String;)V #21 = Utf8 Main #22 = Utf8 java/lang/Object #23 = Utf8 java/lang/System #24 = Utf8 out #25 = Utf8 Ljava/io/PrintStream; #26 = Utf8 java/io/PrintStream #27 = Utf8 println #28 = Utf8 (Ljava/lang/String;)V为什么只看常量池呢,因为在“解析”的定义中提到了:解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。我们来看看常量池中有什么: