HotSpot虚拟机对象如何被创建的?

类的生命周期(类的加载过程)

每个class文件加载到内存到卸载,都是经历过jvm的类的生命周期是加载、连接(验证、准备、解析)、初始化、使用、卸载;

简单介绍后续深入了解!!!

HotSpot虚拟机对象如何被创建的?

java程序中创建对象是通过new出来的,而虚拟机这会就会接收到一条new的指令后,先去检查这个指针是否能够在常量池中找着一个类的符号引用,或找着这个符号引用,则代表这个类经历了加载、解析和初始化过,如果没有那就要执行类的加载过程。当然加载检查全部通过后,虚拟机会为这个类分配内存,当这个类中的所有对象所需的内存大小被加载后就已确认。

内存是如何分配的?

当类加载完成后,这时已经完全确认内存后,分配内存有两种方式:指针碰撞(Bump The Pointer)和维护一张空闲列表(Free List);

指针碰撞(Bump The Pointer):

假设jvm内存是规整(连续意思)的。堆内存被一个指针一分为二。指针的左边是使用过的,内里存放着对象,右边则是空闲的,而指针的作用是当每次新创建对象向右边移动一个对象的size的距离,这种叫做指针碰撞。

个人理解:堆就像连续的一块耕地,左边种上大豆苗子(对象),右边还是空的,当有新的苗子运来的时候接着开始从右边靠近左边空的继续种上,直接种空。(不知道生动不~)

空闲列表(Free List):

假设jvm内存不是规整(连续意思)的,已被使用与空间的内存交错在一起,这时候就无法通过指针碰撞进行分配内存,那就必须维护一张空闲列表,这张表存放着所有空间的地址,当新创建一个对象的时候,需要多少的空间就从表里进行寻找到一位合适的空闲空间进行分配。(当然有大有小,如果大了剩余的是需要被虚拟机回收的,这块jvm对应一套自己的处理机制,这里不赘述,有兴趣可以更深入了解)。

个人理解:这个空闲列表就像有一整块地,有几十亩(内存),有些地房盖上了房子(已用),有些还是空的(未用)。那这时候空的地会被记录在案,当某一天,哪位有钱人家想块地进行盖房子时,就先从这个记录在案里面找一块,然后才进盖房子(创建对象)。

jvm具体选择是空闲列表,还是指针碰撞方式进行内存分配,是根据java堆是否规整来决定,而java堆是否规整又是由垃圾上集器是否带空间压缩整理来决定。(后续垃圾算法详细深入)。

Serial、ParNew等带压缩整理过程收集器采用:指针碰撞。

CMS基于标记清除算法采用:空间列表。

频繁内存分配怎么保证线程安全?

内存分配解决了,但是jvm在分配的时候频繁修改一个指针所指向的位置,在并发情况不是线程安全的,那jvm是通过同步处理和本地线程分配缓冲解决该问题。

同步处理:虚拟机是采用CAS配上失败重试的方式保证更新操作的原子性。

本地线程分配缓冲:每个线程在java堆中预先分配一小块内存,称为地线程分配缓冲(Thread Local Allocation Buffer,TLAB),哪个线程要分配内存,就在哪个线程的本地缓冲区中分配,这块内存分配时线程独占的,读取、使用、回收是线程共享,只有本地缓冲区用完了,分配新的缓存区时才需要同步锁定。

TLAB空间的内存非常小,缺省情况下仅占有整个Eden空间的1%,也可以通过选项-XX:TLABWasteTargetPercent设置TLAB空间所占用Eden空间的百分比大小。由于TLAB空间一般不会很大,因此大对象无法在TLAB上进行分配,总是会直接分配在堆上。TLAB空间由于比较小,因此很容易装满。比如,一个100K的空间,已经使用了80KB,当需要再分配一个30KB的对象时,肯定就无能为力了。这时虚拟机会有两种选择,第一,废弃当前TLAB,这样就会浪费20KB空间;第二,将这30KB的对象直接分配在堆上,保留当前的TLAB,这样可以希望将来有小于20KB的对象分配请求可以直接使用这块空间。

jvm设定TLAB通过:-XX:+/-UseTLAB

比如:使用本地缓存区

-XX:+UseTLAB

注意:

jvm默认采用本地线程分配缓冲来进行解决线程安全问题。

推荐使用虚拟机默认配置,不建议修改TLAB配置。

两种优缺点对比:

名称

同步处理

本地线程分配缓冲

性能

较低

高效

占用空间

不会

会根据运行情况计算而得或配置

最后

简单介绍关于对象被创建的相关流程和条件及内存是如何分配的,这块在面试中倒是经常遇到,希望本文对你有帮助,下文继续关于对象的内存是如何布局的。

参考文章:

https://www.zhihu.com/question/56538259

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值