深入理解Java虚拟机学习日记(2019.10.07)

深入理解Java虚拟机学习日记

第二章:Java内存区域和内存溢出异常

在这里插入图片描述

  1. 程序计数器(PCR):当前线程所执行的字节码行号计数器,占用内存较小。每一个线程(顺序执行单元)都有自己的PCR,如果线程执行的是Java代码,则PCR记录的是正在执行的虚拟机字节码指令的地址;如果执行的是native方法,这个计数器的值为undefined。此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryErroe情况的区域。
  2. Java虚拟机栈:线程私有,生命周期与线程相同。方法的执行与执行完毕都在虚拟机栈中。
    2.1 栈帧:而每个方法的执行都会创建一个栈帧,伴随着方法从创建到执行完毕。栈帧用于局部变量表、操作数栈、动态链接、方法出口等。当虚拟机栈中村放不下栈帧时,会出现stackOverFlowError,递归时出现的概率大。
    2.2 局部变量表:内存空间在编译期完成了分配,之后不会改变大小。存放了编译期克制的各种基本数据类型(如:boolean、byte、char、short等)、对象引用(如:reference类型)和returnAddress类型(指向了一条字节码指令的地址)。其中64位长度的long和double占用两个局部变量空间,其他一个。
  3. 本地方法栈:与虚拟机栈类似,但为native方法服务。
  4. Java堆线程共享区域,存放对象实例并分配内存(几乎所有对象都在此分配内存),是GC管理的主要区域。是Java虚拟机管理最大的一块区域。
    4.1 Eden空间:
    4.2 From Survivor空间
    4.3 To Survivor空间
  5. 方法区线程共享区域,存储虚拟机加载的类信息、敞亮、静态常量、即时编译器编译后的代码等数据。
    5.1 类信息:类的版本、字段、方法、接口等
    5.2 运行时常量池:存放编译器生成的自变量以及符号引用,这部分内容将在类加载后进入到方法区的常量池中引用。
    如String str1;(对象引用)
    String str2 = “abc”;(对象实例化)
    str1 = new String();(对象)
    ------------------------------------------------
    String str1 = new String(“abc”);(两个对象,引用对象str1和实例对象new String(“abc”))
    String str1 = “abc”;
    String str2 = “abc”;
    由于实例都存放在常量池中,先从常量池中查找有无abc内容,若无则创建,有则直接引用,所以str1==str2.
    而new String()则是每次都在堆中创建新的对象。
  6. 对象:创建对象之前需要先加载、解析和初始化类,如果在常量池中没有找到一个类的符号引用,则说明该类还没有被加载,那么则进行累的加载、解析和初始化。
    6.1 给对象分配内存(由于GC导致不同情况)
    在这里插入图片描述
    ## 6.1.1 指针碰撞(当空闲内存比较有规律、连续时)
    在这里插入图片描述
    ## 6.1.2 空闲列表(Java堆不规整时,即空内存多块分布)
    虚拟机维护一个表,记录上哪些内存块可用,在分配是从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录。
    6.2 线程安全性问题:多线程要求同一块空内存。当正在给对象A分配内存是,指针还没来得及修改,对象B又用同一个指针来分配内存。
    ## 6.2.1 线程同步:对分配内存空间的动作进行同步处理。
    ## 6.2.2 本地线程分配缓冲(TLAB):每个线程在Java堆中预先分配一小块内存,哪个线程要分配内存,则在哪个线程的(TLAB)上分配。

当内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),此时创建对象才完成。

  1. 对象的内存布局
    在hotspot虚拟机中分为三个区域:对象头、实例数据和对齐填充(非必要)

    对象头分为两部分,第一部分是用于存储对象自身的运行时数据,如哈希吗、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。长度则根据虚拟机32位或64位分别为32bit和64bit。

    第二部分则是类型指针,即对象指向他的类元数据的指针,虚拟机通过这个指针确定这个对象是哪个类的实例。

  2. 对象的访问定位
    8.1 句柄
    在java堆中划分出一块内存用作句柄池。
    优点:reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要修改。
    8.2 直接指针
    优点:速度更快,节省了一次指针定位的时间开销。
    Alt

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值