【Java】内存区域与对象创建

来源:互联网 发布:c语言node类型 编辑:程序博客网 时间:2024/05/22 11:51

这块内容是java很基础的部分,涉及到JVM的设计原理,很久以前就看到过,这次需要区分线程私有和共享

基本java的运行时数据区可以分为五大块:

程序计数器,为线程私有,每一个线程都有一个,这样线程切换以后才可以恢复上一个线程的现场。

虚拟机栈,为线程私有,非本地方法的运行,每一个线程都有其虚拟机栈

本地方法栈,为线程私有,本地方法的运行

堆,所有线程共享,存放对象和数组

方法区,所有线程共享,存放虚拟机加载的类信息,静态变量和常量

线程私有的数据是线程安全的,通常多线程会出问题的是堆区,也就是对象,多线程修改或读取堆上的同一个对象时会出一些问题,当然java对此有相应的处理,称为内存模型,所谓内存模型就是各个线程使用内存里的变量的规定,当然这里肯定说的是堆区。

对象创建过程:
当虚拟机遇到一条new指令时,首先会看方法区是否有对应的类,如果没有就启动类加载器加载。如果有,就可以通过类定义信息得到该对象需要的内存大小,然后就会申请一块内存区域。申请得到内存以后,会初始化全部的属性为0,然后调用构造方法init来为属性赋值。

对象内存分布:

一个对象的内存分为三个区域,

对象头部,记录了对象的一些status信息,比如说GC年代,hash码,对象锁以及类定义(可能不需要,看实现)等信息

对象的属性

对齐信息

我们都是通过一个引用来操作对象的,通常我们记得可以通过引用得到对象,但是我们还需要得到对象的类型,对象的类型记录在哪里有两个实现:

句柄方式,堆上除了存储对象还存储了对象的句柄,句柄是一个二元信息,<对象位置,类定义位置>。我们的引用实际上是指向了句柄

直接方式,引用直接指向了对象的位置,那么该对象的内存区域还必须包含类定义的位置信息,堆上对象的内存布局需要包含这一信息

使用句柄效率稍差,因为需要定位两次,但是垃圾回收时,对象的位置变化了,只需要修改句柄,所有的引用都可以不变。虚拟机一般使用的是直接方式


原创粉丝点击