zoukankan      html  css  js  c++  java
  • 「每日五分钟,玩转JVM」:对象从哪来

    面向对象

    众所周知,Java是一门面向对象的高级编程语言,那么现在问题来了,对象从哪来呢?有些人会说通过new关键字来创建一个对象,说的很好,本篇我们就来解密在new一个对象的过程中,JVM都给我们做了什么工作。

    走哪来,到哪去

    一个对象的诞生必定有一个类,通常我们都是通过new关键字实例化一个类来获取该类的一个对象,类在加载的过程中会经历一系列的检查,解析,初始化等一系列的过程,我们会在后面详细的分步骤进行讲解,这里我们只关心对象。

    下面对象就要被加载到我们的虚拟机内存的堆内存中,加载到堆内存中也就意味着这个对象需要一定的空间,那么这个空间走哪来呢?这里JVM规范给出了两种情况:

    指针碰撞

    所谓指针碰撞,前提的条件是JVM的堆内存是绝对工整的,中间有一个指针作为分割空闲空间和已用空间的”三八线“,指针碰撞一般发生在Eden区,跟踪在Eden创建的最后一个对象,这个对象会被放在Eden的顶部。如果有足够的空间,对象就会被创建在Eden,并且被放置在顶部,然后将指针向上移动(如果你玩过俄罗斯方块,你就应该明白,说白了就是一种不可消除绝对规整的俄罗斯方块),当俄罗斯方块被堆满之后,就会触发一次Minor GC(关于GC的知识,我们在后面来讲解)

    打个比方来说,一个班里有很多座位,学生必须按照顺序来坐,这样只需要知道最后一个进来的学生坐哪就知道下一个学生坐哪,以及有没有空位~

    image-20190819215012007

    在单线程的情况下,我们这样使用是没有什么问题的,但是如果处于多线程并发的情况,就会出现分配空间失败的情况,打个比方来说,就是把一个位置同时卖给了两个人,这种情况势必就会打架,这种情况下,我们可以采取两种方法来解决这个问题:

    • 使用CAS+失败重试保证更新操作的原子性

    CAS(Compare And Swap),关键是3个操作数。

    内存值V

    旧的预期值A

    要修改的新值B

    当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

    image-20190819222536824

    • 第二种方法,结合我们上节课说到的TLAB来实现,在分配内存的时候在每个线程上的TLAB(Thread Local Allocation Buffer)区域进行分配,这里分配的时候可以初始化为零值,这一步操作保证了对象实例字段在Java代码中不赋值就可以直接使用。

      image-20190819223452177

    Free List

    另一种情况是当堆内存不规整的情况下(学生不要排排坐),JVM会把没来上课的学生(未使用的内存)记到小本本上,当有新学生(新的对象)来上课的时候,可以去看本本上的座位图给学生安排座位~

    这个JVM的小本本就叫做空闲列表(Free List)。

    结语

    到这里,对于虚拟机,对象就已经找到了自己的座位并落座,下一篇,我们来介绍一下对象中都有什么。

    公众号

  • 相关阅读:
    GitLab版本管理
    Failed to add reference to 'System.Net.Http'. Please make sure that it is in the Global Assembly Cache.
    在CentOS 6.3中安装拼音输入法
    Yum Error Another app is currently holding the yum lock; waiting for it to exit
    Centos使用光盘作为本地yum源
    Linux操作系统桌面环境GNOME和KDE的切换
    CentOS安装VMware Tools
    CentOS 加载/挂载光驱
    svn Couldn't open rep-cache database
    linux内存排查工具valgrind
  • 原文地址:https://www.cnblogs.com/viyoung/p/11456892.html
Copyright © 2011-2022 走看看