jvm内存区域和类加载流程

运行时数据区域

程序计数器

​ 是线程私有的,程序计数器是一块较小的内存,它可以看作是当前线程执行的字节码的符号指示令, 它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成 。

Java虚拟机栈

​ 是线程私有的,每个方法被执行时都会调用一个栈帧(方法运行时很重要的基础数据结构)用于存储局部变量表 、操作数栈、动态链接、方法出口等信息。每个方法被调用完毕,就以为这一个栈帧从出栈到入栈的过程。局部变量表存放了运行时可知的各种Java虚拟机的基本类型、对象引用、returnAddress类型(指向了一条字节码指令的地址)。这些数据类型在局部变量表中的存储空间以局部变量槽来表示。其中64位的long、double占两个槽之外,其他都是占用一个槽。

本地方法栈

	为虚拟机栈使用到本地的方法服务 

Java堆

	线程共享区,是虚拟机中所管理的最大的一块区域,此堆的唯一目的就是在jvm启动的时候存放实例。几乎所有的实例对象都在这分配内存。是垃圾回收器管理的内存区域,所以通常来说还分为新生代(From Survivor、To Survivor、Eden空间)、老年代,这样能够更好的回收内容。配置Java堆的大小可以通过参数-Xmx和-Xms设定。如果Java堆中没有内存完成实例的分配,且无法再进行扩展,这时jvm就将抛出OOM异常。

方法区

​ 线程共享区。用于存储已经被jvm加载的类型信息、常量、静态变量、即时编译后的代码缓存等数据。jdk8之前方法区也更被叫做永久代。但是再1.8之后jvm就彻底放弃了永久代的概念,改用再本地内存中实现的元空间来代替。把jdk7中永久代还剩余的内容(主要是类型信息)全部移到元空间内。如果方法区无法满足新的内存分配需求时,则将抛出oom error。

运行时常量池

	是方法区的一部分,class文件除了有版本、字段、方法、接口等信息外,还有一个常量池表,用于存放编译时产生的各种字面量和符号引用。当常量池无法再分配到内存时会抛出oom error。 

类加载的方式

image-20200501001426467

现在来用文字叙述一下类加载的过程:

​ 一般来说创建对象的方式是new关键字(其他比如clone、反序列化),当虚拟机解释到new指令时,首先会去检查这个指令的参数是否在常量池中存在,如果存在则会判断是否已经被加载、解析和初始化等过程。如果没有的话则会进行类加载。

​ 接下来将会在堆中进行内存分配,分配内存也是分两种情况的。第一种就是内存是规整状态,这种情况下,内存区域的指针会分配出一块和对象等大的区域。另一种不规整的,也就是已使用区域和未使用区域重叠在了一起,这个时候的话虚拟机将会维护出一个列表用来存储可用区域。当进行内存分配的时候就能从列表中找到一个足够大的区域划分给实例。

​ 当然这只是正常情况下,并发情况下的话,也并不是线程安全的。容易发生ABA的问题,这里jvm提供了两种解决方案。第一种:对分配空间的动作进行同步操作,也就是通过CAS+失败重试的方式来保证线程安全。第二种:虚拟机会根据线程来划分不同的操作区域(本地线程分配缓冲:TLAB),当每个线程进行内存分配动作的话,会先在划分出的操作区域进行分配,当这块缓冲区域分配完了之后,再进行同步操作。

​ 当内存分配完了之后,虚拟机将会把分配到的内存空间(包括对象头)都初始化为0。

对象访问定位

分为两种方式:

  • 句柄访问

    ​ 句柄访问的话,Java堆将可能会划分出一块区域来作为句柄池,reference种存储的就是存储对象的句柄地址。二句柄种包含了对象实例数据和数据类型各自具体的地址。

    好处是reference中存储的是稳定的句柄地址,将不会受垃圾回收器移动对象的影响,只会改变句柄中的实例数据指针,而reference并不需要修改。

  • 指针访问

    Java堆中对象的内存布局就必须考虑如何放置访问类型数据的相关信息,reference中存储的就直接是对象地址。如果直接访问对象本身的话就不需要多一次间接访问的开销。

    最大的好处是速度更快,由于访问对象在Java中是十分频繁的,所以这个速度的节省也是很可观的。

参考文献:《深入理解Java虚拟机》

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值