深入Java虚拟机- 随笔1

      最近在看 深入Java虚拟机.基本算是浏览式阅读,不过想着总应该记一点,所以特意开了这么一篇内容.下面的所有内容,都是个人觉得书中有意思的东西,算是一个随笔.既然是随笔,那么就不会如记笔记那般对每一章的内容进行归纳概括(其实我个人也觉得没有必要对书中的每一章进行记录),算是一个个小的知识点的Mark.还有很多是个人的理解(或者引用其他的知识解释),并不是原文的copy 废话到此为止.

 

.第五章 Java虚拟机


深入Java虚拟机- 随笔1_第1张图片
 

1 方法区

 

public class Foo {

    public static void main(String[] args){
        Bar bar = new Bar();
        bar.bar();
    }
}
class Bar {
    void bar(){
        
    }
}

 

对应的javap 输出放出来,后面会用到.

写道
Compiled from "Foo.java"
public class Foo extends java.lang.Object
SourceFile: "Foo.java"
minor version: 0
major version: 50
Constant pool:
const #1 = Method #6.#15; // java/lang/Object."<in
const #2 = class #16; // Bar
const #3 = Method #2.#15; // Bar."<init>":()V
const #4 = Method #2.#17; // Bar.bar:()V
const #5 = class #18; // Foo
const #6 = class #19; // java/lang/Object
const #7 = Asciz <init>;
const #8 = Asciz ()V;
const #9 = Asciz Code;
const #10 = Asciz LineNumberTable;
const #11 = Asciz main;
const #12 = Asciz ([Ljava/lang/String;)V;
const #13 = Asciz SourceFile;
const #14 = Asciz Foo.java;
const #15 = NameAndType #7:#8;// "<init>":()V
const #16 = Asciz Bar;
const #17 = NameAndType #20:#8;// bar:()V
const #18 = Asciz Foo;
const #19 = Asciz java/lang/Object;
const #20 = Asciz bar;

{
public Foo();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<i
4: return
LineNumberTable:
line 1: 0


public static void main(java.lang.String[]);
Code:
Stack=2, Locals=2, Args_size=1
0: new #2; //class Bar
3: dup
4: invokespecial #3; //Method Bar."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4; //Method Bar.bar:()V
12: return
LineNumberTable:
line 4: 0
line 5: 8
line 6: 12


}

 

 

下面会描述虚拟机(hotspot)是如何执行Foo.main方法中的第一条指令的(也就是new操作符)

首先,虚拟机被告知需要执行Foo类中的方法,那么,会自动查找并读入"Foo.class"的字节码,存放在方法区中,然后执行方法区中,Foo.class对应的main方法字节码,在整个执行过程中,虚拟机会一直持有Foo类的常量池的指针,

现在虚拟机开始执行第一条指令,也就是new指令.,可以看一下new指令的描述

写道
new

Operation

Create new object

Format


new
indexbyte1
indexbyte2
Forms

new = 187 (0xbb)

Operand Stack

... →

..., objectref

Description

The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (§2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool item at the index must be a symbolic reference to a class or interface type. The named class or interface type is resolved (§5.4.3.1) and should result in a class type. Memory for a new instance of that class is allocated from the garbage-collected heap, and the instance variables of the new object are initialized to their default initial values (§2.3, §2.4). The objectref, a reference to the instance, is pushed onto the operand stack.

On successful resolution of the class, it is initialized (§5.5) if it has not already been initialized.

Linking Exceptions

During resolution of the symbolic reference to the class, array, or interface type, any of the exceptions documented in §5.4.3.1 can be thrown.

Otherwise, if the symbolic reference to the class, array, or interface type resolves to an interface or is an abstract class, new throws an InstantiationError.

Run-time Exception

Otherwise, if execution of this new instruction causes initialization of the referenced class, new may throw an Error as detailed in JLS §15.9.4.

Notes

The new instruction does not completely create a new instance; instance creation is not completed until an instance initialization method (§2.9) has been invoked on the uninitialized instance.

 重点看加粗的说明.我用中文表达一下new指令会做的工作:虚拟机通过计算( (indexbyte1 << 8) | indexbyte2)生成一个指向常量池的索引,然后根据这个索引找到常量池的索引.就是javap输出中的

写道
const #2 = class #16; // Bar

 

该索引必须是CONSTANT_Class_info类型.这时候,可以获取到对应Bar的全额限定名,也就是Bar.虚拟机会检查Bar类是否被加载,这时发现未被装载(多数jvm实现都是通过懒加载来做类的加载的),它就查找并加载Bar类.并放入到方法区中.紧接着,虚拟机会以一个指向方法区Bar类的直接引用替换常量池中Bar的字符引用了(这就是常量池解析)终于.虚拟机为这个对象在堆中创建实例,最后将堆中的实例的实例压入栈顶.至于中间如何计算对象大小,还有如何初始化Bar类,就不在这里多数啦..

 

 

 

你可能感兴趣的:(JAVA虚拟机)