虚拟机在java堆中对象分配、布局和访问的过程

简介: java虚拟机读书笔记 对象的分配、布局、访问

二、虚拟机在java堆中对象分配、布局和访问的过程
  • 一、 对象的创建
    • 1、从java程序,new指令开始,从虚拟机来看,则是判断类是否被加载;
    • 2、类加载通过后,有两个问题:
      • 一、内存分配,
        • 对象所需内存的大小在类加载完成后就可以完全确定,为对象分配空间的任务等于把一块确定大小的内存从Java堆中划分出来。
        • 两种方法:
          • 指针碰撞
          • 空闲列表
        • 分配方式的选择取决于:java堆是否规整;Java堆是否规整取决于:所采用的垃圾收集器是否带有压缩整理功能。
        • 例子:
          • 在使用Serial、ParNew等带有Compact过程的收集器时,系统采用分配算法为:指针碰撞;
          • 使用CMS,基于 Mark-Sweep算法的收集器时,系统采用分配算法为:空闲列表。
      • 二、对象创建的线程安全问题
        • 问题描述
          • 对象创建在虚拟机中的行为非常频繁,即使只是修改一个指针所指向的位置,在并发情况下也并不是线程安全的,有可能出现正在给对象A分配
          • 内存,指针还没有修改,对象B又同时使用了原来的指针来分配内存的情况。
        • 解决方法,有两种:
          • 1 对分配空间的动作进行同步处理;
            • 实际上虚拟机采用CAS配上失败重试的方式保证更新操作的原子性;
            • CAS(比较与交换,Compare and swap)是一种有名的无锁算法。(ConcurrentHashMap也用到了此算法)
          • 2 本地线程分配缓冲
            • 把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在java堆中预先分配一小块内存,称为本地线程分配缓冲(Tlab)。
            • 虚拟机是否使用Tlab,可以通过-XX:+/-UseTlab参数来设定
    • 3、对象内存分配完成后,虚拟机把内存空间初始化
      • 虚拟机将分配到的内存空间都初始化为零值(不包括对象头),如果使用Tlab,初始化操作可以提前至Tlab分配时进行。
      • 目的:
        • 保证了对象的实例字段在java代码中可以不赋初始值就可以直接使用,程序能访问到这些字段的数据类型所对应的的零值。
    • 4、修饰对象
      • 虚拟机对对象进行必要的设置。其实是对象头。
      • 对象头中包括:对象的哈希码、对象的Gc分代年龄、此对象是哪个类的实例、类的元数据信息的指示等;
      • 根据虚拟机当前的运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。
    • 5、对象产生
      • 从虚拟机的角度,一个新的对象已经产生。
      • 从java程序的角度,对象创建才刚刚开始,init方法还没有执行,所有的字段都为零。
        • 一般来说(由字节码中是否跟随invokespecial指令所决定),执行new 指令之后会接着执行方法,
        • 把对象按照程序员的意愿进行初始化,这样一个真正可用的对象产生。
  • 二、 对象的内存布局
    • 对象在内存中布局分配分为三个部分
      • 对象头
      • 实例数据
      • 对齐填充
    • 1 、对象头
      • 如图:
        746053c1-0024-4667-80f9-6cace6fa994e-5210562.jpg
      • 第一部分
        • 用于存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,
      • 第二部分
        • 类型指针,即对象指向它的类元素数据的指针,虚拟机通过该指针确定对象的实例是哪个类。
    • 2 、实例数据
      • 对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。
      • 包括父类继承的,子类定义的;
      • 存儲順序: 虚拟机分配策略参数和字段在java源码中定义的顺序 ;
      • hotSpot虚拟机默认的分配策略为longs/doubles、ints、 shorts/chars、bytes/booleans、oops(Ordinary Object Pointers),
      • 相同宽度的字段被分配到一起。在这个前提下,父类中定义的变量会出现在子类之前。
    • 3 、对齐填充
      • 不是必须存在的,只是占位符的作用。
      • 因为对象的大小必须是8字节的整数倍。对象头部分正好是8字节的倍数,当对象实例数据部分没有对齐时,通过对齐填充补全。
  • 三、 访问
    • 访问方式有2个,句柄和指针:
      • 句柄访问
        f502ca94-6fc3-4bb3-ac78-8f7c7c52d34c-5210562.jpg
        • 存储位置:java 堆中划分一块内存作为句柄池,reference中存储的就是对象的句柄地址;
        • 包含信息:对象实例数据与类型数据各自的具体地址信息。
      • 指针访问
        9a55bcb9-2a0b-4f82-8031-84036ee1b25f-5210562.jpg
        • reference 存储的直接就是对象地址。
        • 问题: 考虑java堆对象的布局中存放访问类型数据的相关信息。
    • 两种方法的优劣:
      • 句柄
        • reference中存储的是稳定的句柄地址,对象被移动时,只改变句柄中的实例数据指针,而reference本身不需要修改。(在垃圾收集时移动对象时普遍的)
      • 指针
        • 速度更快,节省了一次指针定位的时间开销。--由于对象的访问在java非常频繁。(积少成多)
    • Sun HotSpot 采用第二种方式

相关文章
|
1月前
|
监控 Java 中间件
8G的容器Java堆才4G怎么就OOM了?
本文记录最近一例Java应用OOM问题的排查过程,希望可以给遇到类似问题的同学提供参考。
|
6月前
|
存储 算法 Java
惊!Java程序员必看:JVM调优揭秘,堆溢出、栈溢出如何巧妙化解?
【8月更文挑战第29天】在Java领域,JVM是代码运行的基础,但需适当调优以发挥最佳性能。本文探讨了JVM中常见的堆溢出和栈溢出问题及其解决方法。堆溢出发生在堆空间不足时,可通过增加堆空间、优化代码及释放对象解决;栈溢出则因递归调用过深或线程过多引起,调整栈大小、优化算法和使用线程池可有效应对。通过合理配置和调优JVM,可确保Java应用稳定高效运行。
182 4
|
2月前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
2月前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
102 5
|
3月前
|
安全 Java 编译器
Java对象一定分配在堆上吗?
本文探讨了Java对象的内存分配问题,重点介绍了JVM的逃逸分析技术及其优化策略。逃逸分析能判断对象是否会在作用域外被访问,从而决定对象是否需要分配到堆上。文章详细讲解了栈上分配、标量替换和同步消除三种优化策略,并通过示例代码说明了这些技术的应用场景。
Java对象一定分配在堆上吗?
|
4月前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。
|
4月前
|
存储 算法 Java
🏗️Java零基础:深入了解Java 堆
【10月更文挑战第2天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
53 3
|
5月前
|
存储 算法 Java
深入解析 Java 虚拟机:内存区域、类加载与垃圾回收机制
本文介绍了 JVM 的内存区域划分、类加载过程及垃圾回收机制。内存区域包括程序计数器、堆、栈和元数据区,每个区域存储不同类型的数据。类加载过程涉及加载、验证、准备、解析和初始化五个步骤。垃圾回收机制主要在堆内存进行,通过可达性分析识别垃圾对象,并采用标记-清除、复制和标记-整理等算法进行回收。此外,还介绍了 CMS 和 G1 等垃圾回收器的特点。
159 0
深入解析 Java 虚拟机:内存区域、类加载与垃圾回收机制
|
5月前
|
JSON 前端开发 JavaScript
java中post请求调用下载文件接口浏览器未弹窗而是返回一堆json,为啥
客户端调接口需要返回另存为弹窗,下载文件,但是遇到的问题是接口调用成功且不报错,浏览器F12查看居然返回一堆json,而没有另存为弹窗; > 正确的效果应该是:接口调用成功且浏览器F12不返回任何json,而是弹窗另存为窗口,直接保存文件即可。
221 2
|
4月前
|
存储 算法 Java
【用Java学习数据结构系列】用堆实现优先级队列
【用Java学习数据结构系列】用堆实现优先级队列
58 0

热门文章

最新文章