深入理解Java虚拟机(二)——HotSpot对象创建、内存、访问
对象的创建
虚拟机遇到一条字节码new指令时,开始对象创建过程。
- 首先去检查这个指令的参数是否能在常量池定位到一个类的符号引用;
- 检查这个符号引用代表的类是否已被加载、解析和初始化,如果没有就必须执行相应的类加载过程;
- 根据方法区中该类的信息确定对象的所需空间大小;
- 虚拟机为新生对象分配内存;
- 将对象实例的内存(不包括对象头)进行初始化为零值;
- 配置对象头的信息;
- 调用对象的构造函数进行初始化。
这样,一个真正可用的对象被完全构造出来了。
多线程中,引用指向对象的内存空间和对象初始化操作可能会出现重排序,这样会导致对象没有初始化就被其他线程使用了,就会出错。方法这种情况,就需要将对象声明为volatile。《Java并发编程艺术》
分配内存方法
虚拟机为新生对象分配内存有两种方法:
- 碰撞指针:如果虚拟机垃圾收集器采用的复制算法或者标记-整理算法,那么堆中空闲内存和已使用过的内存是连续放在一块的,二者中间存在一个指针作为分界点的指示器。这样分配内存的时候,只需要将指针向空间区域挪动一段与对象大小相同的距离,这种方式就是指针碰撞。
- 空闲列表 :如果虚拟机垃圾收集器采用的标记-清除算法:那么堆中的空闲内存和已使用内存不是连续的,是交错的,虚拟机通过维护一张列表来记录可用内存块,在分配内存的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表,这种分配方式就是空闲列表。
所以,虚拟机采用何种内存分配方法,取决于其所用的垃圾回收算法。
并发时对象分配
解决并发时对象分配的问题:即使仅仅修改一个指针所指向的位置,在并发情况下也并不是线程安全的,可能出现正在给对象A分配内存,指针还没来得及修改,对象B又同时使用了原来的指针来分配内存的情况。
两种方案可以解决:
- 通过CAS配上失败重试的方法可以保证操作的原子性。
- 通过给每个线程一个本地线程分配缓冲区,当线程需要分配内存时,就在它相应的缓冲区分配,当缓冲区耗尽,就进行同步锁定。
对象的内存模型
对象在堆内存中可以划分为三个部分:
- 对象头
- 实例数据
- 对齐补充
1.对象头
对象头包括两类信息:
- 第一类用于存储对象自身的运行时数据:例如哈希码、GC分代年龄、锁状态、线程持有的锁、偏向线程ID、偏向时间戳等。
- 可能还存在第二类是类型指针,就是对象指向它的类型元数据指针,虚拟机通过这个指针来确定该对象是哪个类的实例。
- 如果是Java数组对象,对象头重还必须有一块数据用于记录数组的长度。
2.实例数据
是对象真正存储的有效信息,就是在程序代码里面定义的给中类型的字段内容,成员变量的值,其中包含父类的成员变量和当前类定义的变量。
3.对齐填充
作用只是占位符。并不是必然存在的。
HotSpot要求对象的起始地址必须是8子节的整数倍,所以任何对象的大小都必须是8子节的整数倍。对象头已经被设计为8字节的整数倍,如果实例数据没有对齐,就需要通过对齐填充部分进行补全。
对象访问定位
Java程序会通过栈上的reference数据来操作堆上的具体对象。所谓reference类型就是一个指向对象的引用。
主流的访问方式有两种:
- 使用句柄访问:
堆中划分出一块内存作为句柄池,用于存放对象实例数据和类型数据各自的地址信息。Java栈中存放的引用指向句柄池中对象的句柄地址。 - 直接指针访问:
引用类型指向的是对象的地址,不需要句柄池直接访问对象。但是对象的内存中就需要放置访问类型数据的相关地址信息。
比较:
- 句柄访问的好处是句柄地址稳定,当对象被垃圾收集器移动时,只会改变句柄池中的实例数据地址,而本地变量表中的引用不需要被修改。
- 直接指针访问的好处就是速度快,节省指针定位的时间开销。HotSpot主要采用这种方式进行访问。


深入理解Java虚拟机(二)——HotSpot对象创建、内存、访问的更多相关文章
- 深入理解Java虚拟机二:垃圾收集与内存分配
垃圾收集:垃圾收集要完成三件事,包括哪些内存需要回收,什么时候回收及如何回收. 1.需要回收的内存判定:没有引用指向原先分配给某个对象的内存时,则该内存是需要回收的垃圾 Java垃圾收集器在对内存进行 ...
- 深入理解Java虚拟机二 阅读笔记
xl_echo编辑整理.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!! --- > 以下内容摘抄自 ...
- 深入理解Java虚拟机:垃圾收集器与内存分配策略
目录 3.2 对象已死吗 判断一个对象是否可被回收 引用类型 finalize() 回收方法区 3.3. 垃圾收集算法 1.Mark-Sweep(标记-清除)算法 2.Copying(复制)算法 3. ...
- 《深入理解Java虚拟机》学习笔记之内存分配
JVM在执行Java程序的过程中会把它所管理的内存划分若干个不同的数据区域,如下图: 大致可以分为两类:线程私有区域和线程共享区域. 线程私有区域 程序计数器(Program Counter Regi ...
- 《深入理解java虚拟机》读书笔记1--java内存区域
Java内存管理 本文主要介绍Java虚拟机运行时的内存区域是如何划分的.Java对象的创建过程.Java对象的内存布局.Java对象的访问定位 一:运行时区域划分 主要可以分为以下 几个: 程序计数 ...
- java虚拟机(三)--HotSpot 对象
普通对象的创建(不包括数组和class对象): 当虚拟机遇到new指令时,会在常量池中检查是否包含这个类的符号引用(全限定名),通过这个确定是否经过类加载的过程,如果true,为该 对象分配内存,对象 ...
- 深入理解Java虚拟机(四)——HotSpot垃圾收集器详解
垃圾收集器 新生代收集器 1.Serial收集器 特点: 单线程工作,收集的时候就会停止其他所有工作线程,用户不可知不可控,会使得用户界面出现停顿. 简单高效,是所有收集器中额外内存消耗最少的. 没有 ...
- 深入理解Java虚拟机二之Java内存区域与内存溢出异常
运行时数据区域 1.线程独有的内存区域 PROGRAM COUNTER REGISTER 程序计数器 程序计数器空间较小,是当前线程执行字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值 ...
- 深入理解Java虚拟机笔记——垃圾收集器与内存分配策略
目录 判断对象是否死亡 引用计数器算法 可达性分析算法 各种引用 回收方法区 垃圾收集算法 标记-清除算法 复制算法 标记-整理算法 分代收集算法 HotSpot算法实现 枚举根节点 GC停顿(Sto ...
随机推荐
- Android自定控件基础(一)——几何图形绘制
虽然本人有几年开发经验,但是自定义控件这一块儿,研究的很少,惭愧--用到的时候就是百度查找,复制粘贴.工时紧,总是想的快点完工就好.(都是借口啦,想学总会有时间哒) 作为一个Android开发 要说自 ...
- centos6 virbox安装
yum install kernel-devel yum update kernel* wget http://download.virtualbox.org/virtualbox/debian/or ...
- 加解密 C语言实现
1.加密的基本原理 加密分为对称加密和非对称加密,对称加密就是加密方和解密放用同一个密钥. 加密是分组加密,即将明文数据分成多个密钥大小的块,依次和密钥运算,输出密文. padding,由于加密需要分 ...
- HashMap 链表插入方式 → 头插为何改成尾插 ?
开心一刻 一天,楼主在路上碰到了一个很久没见的朋友,找了个餐馆,坐下聊了起来 楼主:在哪上班了 ? 朋友:火葬场啊 楼主:在那上班,一个月多少钱啊 ? 朋友:两万多啊 楼主(不可思议):多少 ? 朋友 ...
- Dubbo 接口,导出 Markdown ,这些功能 DocView 现在都有了!
前言 自从 DocView 发布了简陋的第一版之后,就不断地有小伙伴提建议意见等等,希望扩展各种功能.这不,时隔两周,DocView 又发布了新版本,本次的更新主要涉及到支持 Dubbo,以及支持导出 ...
- echarts折线图,数据切换时(最近七天)绘图不合理现象
echarts折线图,当进行数据切换时存在绘制不合理的问题,数据没错,但绘制不对. 两个0之间的连线应该是平滑直线,如图: 正确的显示: 解决: 在myCharts.setOption(option) ...
- Django启动服务的流程
我晕,启动个服务浪费快一个小时的时间,记录下步骤吧. 1.D:\django\newworld>python manage.py runserver Performing system chec ...
- Boost命令行解释器的简单使用:Boost.Program_options
简介 如果使用比较多的命令行程序的话,对于命令行参数的输入肯定不会陌生,大部分的程序都是通过类似下面的形式进行输入的,比如熟悉的ls ls --all -l --color=auto 这里面包含了三种 ...
- burp插件之跨站payload批量注入-xssValidator
环境搭建 Phantomjs下载 csdn-burp使用xssValidator插件 cnblog-burp插件之xssValidator xssValidator使用 参考链接 cnblog-bur ...
- Linux 学习笔记01丨Ubuntu系统安装、配置及软件教程集合
1. Ubuntu系统安装 Windows10安装ubuntu18.04双系统教程 Ubuntu 20.04.1 镜像下载 软碟通 机械革命进入BIOS模式 要按F2,注意将Boot Option中将 ...