运行时数据区域
对象的创建与访问定位
- 堆和方法区:都是为了共享资源而设计,逻辑上是等价的。但是方法区更侧重于保存"结构":存储运行时常量池,class信息,静态变量等,这些结构是更难解析,更难回收,并非GC的主要目标,可以用永久代实现。 而堆更侧重保存"数据元":存放对象Instance,物理上并非连续,可以动态扩展,但不可超出可分配内存,否则OOM,是GC的主要目标,在堆内对Instance进行分代,以便更好的回收。简单的说:方法区是一个个class、堆上是这些class new出来的一个个对象
- Java虚拟机栈:线程私有,与线程同生命周期,这也就意味着N个线程存在N个栈,每个栈首先要有PC,即决定当前是哪个线程在执行,下一个pc地址代表哪个线程将会被执行。在每个线程栈中会依次入栈当前方法、当前对象、当前变量等。当请求的栈超过物理深度时会报StackOverflowError。
- 虚拟机栈-变量弹栈:执行变量 x 和存取地址(store load addr)
- 虚拟机栈-方法:A调用return的方法B时,A入栈,调用B,return_B入栈,操作B,return_B弹栈,A弹栈
- 对象创建:以Person zhangsan = new Person()为例,分为两步,可以当成编译器在扫描时将Person zhangsan =入栈,然后将new Person()入栈;步骤一,弹栈,取出new Person(),new是一个申请内存的指令,依次会通过类型检查,分配全为默认值的内存空间(除了对象头,此时对象头部已经存在)。步骤二,弹栈,取出Person zhangsan = ,对步骤一new出来的内存空间用zhangsan的name,age等属性进行初始化
- 对象的访问定位:zhangsan的引用弹栈,引用中存放的是堆中zhangsan的地址(reference = C++中指针),而堆中zhangsan的对象头Object Header中存放了方法区的Person.class的地址(反射?)