《深入理解java虚拟机》读书笔记1--java内存区域

Java内存管理

本文主要介绍Java虚拟机运行时的内存区域是如何划分的、Java对象的创建过程、Java对象的内存布局、Java对象的访问定位

一:运行时区域划分

主要可以分为以下 几个:

  程序计数器;

  栈(虚拟机栈和本地方法栈);

  堆;

  方法区;

1.程序计数器

  记录正在执行的虚拟机字节码指令的地址.唯一一个没有规定任何OutOfMemoryError的区域。

2.栈

  栈主要用来存储局部变量表(各种局部变量(方法中的变量),基本类型和对象引用类型)、操作数栈、动态链接等信息。线程私有的。所以方法中的变量不是线程共享数据。

  虚拟机栈和本地方法栈比较相似,他们的区别是虚拟机栈为虚拟机执行Java方法服务,本地方法栈为虚拟机使用到的native方法服务。

3.堆

  堆是Java虚拟机管理的内存最大的一块。虚拟机启动时创建,用于存放所有的对象实例以及数组。各个线程共享,所以,对象数据是共享数据。

4.方法区

  各个线程共享区域。存储已被虚拟机加载的类信息、常量、静态变量等。这些数据都是共享数据

二:对象创建

类加载->分配内存->初始化为0->设置-><init>

类加载:第七章

内存分配:指针碰撞和空闲列表

  指针碰撞:当堆中内存是绝对规整的,用此方法。此内存可以看做两部分,一边是使用过的内存,另一边是空闲的内存,中间用一个指针隔开。分配内存时,只需将指针向空闲内存那边移动一段与对象大小相等的距离即可。

  空闲列表:当堆中内存不是规整时用此方法。虚拟机必须维护一个列表,该表记录了哪些内存块是可用的,在分配的时候找到一块足够大的区域分配,并更新表上的记录即可。

设置:对象头的信息进行设置。

<init>:按照程序员的意愿进行初始化。

三:对象的内存布局 

对象的内存布局可以分为三块区域:对象头、实例数据和对齐填充。

对象头:主要包含两部分信息:1,用于存储对象自身运行时数据,如哈希码、GC分代年龄、线程持有的锁、锁状态标志等;2,类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例;3,如果对象是数组,对象头还要有数组长度。

实例数据:对象真正存储的有效信息,代码中定义的各种字段,包括父类的。

对齐填充:充当占位符。对象的大小必须是8字节的整数倍,对象头正好是8字节的整数倍。

四:对象的访问定位

Java程序需要通过栈上的对象引用数据来操作堆上的具体对象。有两种访问方式:使用句柄和直接指针。

使用句柄:在Java堆中划分一个区域来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和对象类型数据(类数据)的地址信息。如图:

直接指针访问:reference中存储的直接就是对象的地址,而堆对象中就必须考虑 如何访问类型数据的相关信息.

原文地址:https://www.cnblogs.com/xiaolovewei/p/8022194.html