学过JVM的人都知道在JVM中在执行Java程序的过程中会把JVM管理的内存进行划分,叫做运行时数据区

JVM中管理的内存主要分为以下五个部分:

  1. 方法区Method Area):

  2. Java堆Heap):Java堆是JVM管理内存中最大的一块区域,几乎所有的Java对象的内存都在这里分配,此区域也是GC最活跃的区域。

  3. 虚拟机栈VM Stack):此区域就是我们通常所说的“”,当线程执行方法时会在此区域创建一个栈帧,用于储存局部变量表动态链接方法出口等信息。

  4. 本地方法栈Native Method Stack):本地方法栈虚拟机栈类似,只不过本地方法栈执行的是Native方法服务。

  5. 程序计数器Program Counter Register):是当前线程执行字节码的行号指令器,是线程私有的。

当执行一个Java方法时,程序计数器记录的是JVM正在执行的字节码指令,若是执行的是本地方法,程序计数器为空。


这五个部分都有自己的功能,有些区域是线程私有的,会跟随着线程的创建和销毁,有些区域是跟随进程的启动而存在,各自承担着自己的职责。

在方法区中还有一块区域就是常量池,很多人叫它为永生代 PermGen(JDK 1.7的说法)。

随着JDK8的到来,JVM不再有PermGen。但类的元数据信息还在,不再是存储在连续的堆空间上,而是移动到叫做Metaspace(元空间)的本地内存(Native memory)中。

我们知道当我们执行创建对象的时候,就会初始化对象的属性信息,例如执行如下的代码:

public class TestObj {private int n=1;public static void main(String[] args) throws Exception {TestObj obj =new TestObj();}
}

该代码非常的简单,在main方法中执行TestObj obj =new TestObj()就会初始化该对象的成员变量n为1,我们都知道这个过程叫做初始化,在初始化的时候也会进行半始化。

那么什么叫做半初始化呢?

半初始化就是当一个成员变量还未初始化为它真正的值,会先初始化为它默认是的值,例如int会先初始化为0boolean会先初始化为false等。

对于半初始化,真正的讲清楚要从执行的字节码指令分析,下面我们通过字节码指令进行深入的分析,一个对象的初始化过程。

具体在idea中查看字节码指令的方法可以自行百度,这个不难,通过idea中可以查看上面代码执行的指令,如下所示:


在上面mian方法中执行完,也就是对应这五条指令,如下所示:

  1. new指令:表示首先在堆中申请一块内存,此时堆中的内存中存储着该对象属性n的半初始化状态值n=0。

  2. dup指令:表示复制引用。

  3. invokespecial指令:表示调用对象的初始化方法,后面对应的注释Method "",此时属性值n才会被初始化为1。

  4. astore_1指令:此时会将TestObj obj =new TestObj()的引用obj 与该堆中的对象建立连接。

  5. return指令:执行完最后返回。

从上面的指令中分析可以看出,当创建一个对象的时候,主要分为以下三个步骤,执行的原理图如下:


了解完对象的半初始化,那么什么又是对象分配?

说到JVM中的对象分配,我们得从对象在JVM中执行new指令后开始讲起。客观且慢,请听我详细道来。

在JVM中当遇到一条new指令时,会首先检查这条指令的参数是否在常量池中能定位到一个类的符号引用,若是定位不到,就表示没有被加载、解析和初始化过,就会先执行加载该类。

JVM中加载类信息的详细过程,请参考这一篇文章[面试官:你知道java类是怎么跑起来的吗?问的我一脸懵]。

若是存在该符号引用表示之前已经加载过该类信息,接下来就直接执行在堆中进行对象内存的分配。

但是随着JVM的发展,JIT编译器的出现,所有的对象分配在堆中就不那么绝对了,当创建对象为对象分配内存时,也会尝试在栈上分配,在JVM书籍中的描述如下所示:


那么什么是逃逸技术? 每个线程执行方法都会创建一个栈帧,该栈帧用于存储方法的局部变量,当一个变量不会在其他方法中使用到,只在该方法中使用,就不会逃逸。

什么又是变量替换呢? 标量替换就是创建一个对象的时候,直接以对象的属性进行入栈存储,方法结束后直接弹栈结束,不会有GC的介入。

因此,在栈上分配是对JVM的一种优化措施,减少了GC的活动,提高了Java虚拟机的执行效率。

当对象执行在堆上进行内存分配的时候,为了防止多线程分配内存存在混乱的情况,通常在多线程的时候对对象内存的分配    有以下两种方案进行解决:

  1. 对分配内存的动作进行同步,但是同步的的操作太消耗性能,大大降低了JVM的性能。

  2. 对堆内存为每一个线程划分一块本地线程分配缓冲TLAB),是线程私有的,这样每一个线程只需要在自己的TLAB中进行分配即可,就不用进行同步,也能达到线程安全的目的:

那么当一个对象在堆中分配完一个内存后,对象在堆中又是怎么存在的呢?

客观不急请听我慢慢道来,当对象在堆中进行完内存分配后,一个普通对象在堆中以如下图的形式存在:

  1. markword:存储的是锁信息、对象的年龄信息等。

  2. class pointer:类型指针指向该对象class类型。

  3. instance data:实例数据,储存对象实例的数据值。

  4. padding:对其若是该对象的大小不能被8字节整除,就会自动补齐为8字节的整数倍。

那么对象都已经存在堆中了,我们又是怎么访问该对象的?

若要访问堆中已经存在的对象,有以下两种方式:

(1) 句柄的方式:会在堆中划分一块下的内存作为句柄池,对象的引用不会直接存储数据的地址,而是指向句柄池的指针,由句柄池的指针存储数据的地址。

句柄池的方式,由于对象引用不会直接指向数据的地址,这样当GC进行回收垃圾的时候,移动对象,对象的地址改变了就不用改变reference的本身内容。

这个也是句柄访问方式的唯一优点,具体句柄访问方式的原理图如下所示:

(2) 直接方式:直接方式是reference直接指向数据的,这样减少了一次指针的定位,速度快,直接访问的方式原理图如下:

注意: 在HostSpot的源码实现中,使用的是第二种直接访问的方式

特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:长按订阅更多精彩▼如有收获,点个在看,诚挚感谢

你的对象在哪里?长什么样?我带你去看一看相关推荐

  1. 邮件内容会留在服务器吗,outlook的邮件最长可以保存多久,去

    outlook的邮件最长可以保存多久,去年的邮件还可以找到吗?如何设置不自动删除过期的? 问题来自: 2020-01-01 0 / 200 提交回答 2021-07-30 关于 outlook的邮件最 ...

  2. 假设有一条绳子长3000m,每天剪去一半,请问需要几天时间,绳子的长度会短于五米?

    假设有一条绳子长3000m,每天剪去一半,请问需要几天时间,绳子的长度会短于五米? 代码 package duanyuwu;public class duanyuwu {public static v ...

  3. AIDA64压力测试教程,AIDA64压力测试多长时间,AIDA64压力测试结果怎么看

    硬件管理工具AIDA64功能全面专业,操作简便易学,使用AIDA64进行系统稳定性测试逐渐成为更多用户的选择.可能有很多用户对如何使用AIDA64进行系统稳定性测试不太了解,系统稳定性测试也称为压力测 ...

  4. 激发数学思维!一个烧脑的顶级数学纪录片《维度:数学漫步》完整版,带你漫步数学之美!时长125分,建议先马再看!看完从此爱上数学!

    激发数学思维!一个烧脑的顶级数学纪录片<维度:数学漫步>完整版,带你漫步数学之美!时长125分,建议先马再看!看完从此爱上数学! https://www.bilibili.com/vide ...

  5. 在Linux环境下使用gfortran编译器生成fortran语言的.so共享对象文件 并使用JNA调用 带参方法

    在Linux环境下使用gfortran编译器生成fortran语言的.so共享对象文件 并使用JNA调用 带参方法 1 致谢和参考文章 1.1 致谢 1.2 参考文章 2 环境介绍 3 整体思路 4 ...

  6. 如何查看长文本的标识和对象(读长文本)。

    以物料主数据中长文本和销售订单中长文本为例. 一.查看物料主数据中长文本标识. 先mm02(显示的TCODE不行),工具栏中的"附加数据" 1.基本数据文本:点编辑器," ...

  7. 微信小程序页面跳转url传参,对象数据过长问题

    小程序url传参如果是对象的话需要先用JSON.stringify()转换一下,接受页面在用JSON.parse()再转换回来. 但这样传参有一个问题,当对象数据长度过大时会报错,因为url传参时程序 ...

  8. 第八周项目二-用对象数组操作长方柱类

    /* *Copyright(c)2016,烟台大学计算机与控制工程学院 *All rights reserved *文件名称:123.cpp *作 者:王蕊 *完成日期:2016年4月19日 *版 本 ...

  9. 月薪2W+的程序员简历长啥样?来来来,看这里

    想要成为合格的Java程序员或工程师到底需要具备哪些专业技能,面试者在面试之前到底需要准备哪些东西呢? 本文陈列的这些内容既可以作为个人简历中的内容,也可以作为面试的时候跟面试官聊的东西,你可以把这些 ...

最新文章

  1. A Strange Bitcoin Transaction
  2. Google Brain团队最新视频介绍
  3. VR技术怎么落地,行业应用怎么挖掘,来江苏虚拟现实发展大会侃侃
  4. Photoshop激活教程
  5. Linux之Debian下安装LAMP apt-get安装方式
  6. PHP通过PDO连接Microsoft Access数据库
  7. sql loader 参数详解
  8. python循环遍历把表写入csv_求教python3.5如何把字典循环写入csv?
  9. Java小项目 屏幕自定义尺寸GIF生成器V1.0
  10. SPI 读取不同长度 寄存器_MCGS触摸屏如何实现批量读取modbus数据的方法?
  11. 《潮流时装设计——世界顶级时装CAD制板技巧》——1.2 国内外服装CAD的发展状况...
  12. 怎么在oracle建表,在linux怎么操控oracle建表
  13. 与时俱进的迅捷多功能转换器
  14. Weblogic10.3.6反序列化漏洞补丁更新
  15. 传统Tier1“大象转身”:不够快?你永远没有机会
  16. 扬州大学计算机专业考研分数,扬州大学考研分数线
  17. APS Interview - Digital Circuit and Digital Logic I
  18. 15nm粒径球形纳米金AuNPs-Thrombin修饰R-藻红蛋白/阿霉素的制备过程
  19. 跨境电商“洋码头”,真正的对手是谁?
  20. 计算机软件相关参考文献,计算机软件论文参考文献范文.doc

热门文章

  1. 【C语言】模拟实现库函数 strcpy(复制字符串内容) 与 strlen(求字符串长度)
  2. python 序列化函数_python – 如何序列化sympy lambdified函数?
  3. 广东2021高考成绩查询6,2021全国高考6月10日全部结束 预计最快6月23日可查高考成绩...
  4. 文件转换html文件失败,pandoc文档转换失败,出现错误67
  5. 0x43.数据结构进阶 - 线段树
  6. 最长公共子序列(LCS)问题算法详解+例题(转换成LIS,优化为O(nlogn),看不懂你来打我)
  7. for循环10000次花多长时间_java循环经典案例学会它入行java
  8. P - The Shortest Path in Nya Graph HDU - 4725
  9. mysql innodb插件_mysql安装innodb插件
  10. mysql数据库多级分类汇总_sql多级分类汇总实现介绍