读深入理解JVM虚拟机-new/对象创建

读深入理解JVM虚拟机-new/对象创建

背景

  • 作为java程序猿很好奇:实用很频繁的new指令,jvm在new的时候是怎么样的一个过程.

过程简述

加载类信息

  • 在遇到一个new指令的时候,必须要先检查这个new指令的的参数能否在<font color=red>常量池</font>中定位一个类的符号引用,并检查,这个类是否已经被加载、解析、初始化.

分配内存

  • 任何对象的内存分配都在<font color=red>类加载完成后</font>便可完全确定.
  • 然后分配的时候,拿这一块确定大小的内存在java堆中划分出来.
两种方法

指针碰撞

  • 当java堆内存是规整的,空闲内存和使用过的内存放在两侧,中间有个指针进行作为分界点的指示器.分配内存移动指针就够了,这种分配方式叫做<font color=red>指针碰撞</font>
    image.png

空闲列表

  • 如果java堆内存并不规整,空闲内存和使用过的内存互相交错,那么java堆必须维护一个列表(记录那些内存可用),分配时找到足够大的内存分配给对象实例,并且记录在列表中,这种分配方式叫做<font color=red>空闲列表</font>
线程安全问题
  • new指令是非常频繁的指令,即时是一个简单的移动指针,也会遇到线程安全问题.

CAS(COMPARE AND SWAP)

  • 以后会详述

TLAB(Thread LOCAL ALLOCATION BUFFER)

  • 为了解决线程安全问题,每个线程,在java堆中预先分配一部分内存,称之为本地线程分配缓冲,哪个线程需要分配内存,就在哪个线程的TLAB上分配,<font color=red>只有在TLAB用完了,并分配新的TLAB时才会同步锁定.</font>
  • 通过-XX:+/-UseTLAB参数来设定
  • 如果使用此方式,那么下一步的初始化零值,可以在TLAB中完成

初始化零值

  • jvm需要将分配的存储空间(不包括对象头),这以操作保证了对象的实例字段在java代码中可以不赋初始值就可以直接使用,程序能访问到的这些字段的数据类型对应的零值.

设置对象头(object header)

  • 后面会进行详细介绍

执行init方法

  • 经历过上述步骤之后,对象就可以使用了,但是所有的字段都是零值.所以执行new指令之后,会执行init方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生.
程序
  • hotspot/bytecodeinterpreter.cpp
//确认常量池中存放的是已经解释的类
if (!constants->tag_at(index).is_unresolved_klass()) {
          // 断言确保是klassOop和instanceKlassOop
          Klass* entry = constants->slot_at(index).get_klass();
          assert(entry->is_klass(), "Should be resolved klass");
          Klass* k_entry = (Klass*) entry;
          assert(k_entry->oop_is_instance(), "Should be InstanceKlass");
          InstanceKlass* ik = (InstanceKlass*) k_entry;
      //确保对象所属类型已经经过类初始化阶段
          if ( ik->is_initialized() && ik->can_be_fastpath_allocated() ) {
            //取对象长度
            size_t obj_size = ik->size_helper();
            oop result = NULL;
            // 记录是否需要将对象所有的字段置零
            bool need_zero = !ZeroTLAB;
        //是否在TLAB中分配对象
            if (UseTLAB) {
              result = (oop) THREAD->tlab().allocate(obj_size);
            }
            if (result == NULL) {
              need_zero = true;
             //尝试分配到eden区中分配对象
        retry:
              HeapWord* compare_to = *Universe::heap()->top_addr();
              HeapWord* new_top = compare_to + obj_size;
          //cmpxchg是x86中的CAS指令,这里是一个C++方法,通过CAS方法分配空间,如果失败,那么赚到retry重试,知道分配成功
              if (new_top <= *Universe::heap()->end_addr()) {
                if (Atomic::cmpxchg_ptr(new_top, Universe::heap()->top_addr(), compare_to) != compare_to) {
                  goto retry;
                }
                result = (oop) compare_to;
              }
            }
            if (result != NULL) {
              // 如果需要,则为对象初始化零值
              if (need_zero ) {
                HeapWord* to_zero = (HeapWord*) result + sizeof(oopDesc) / oopSize;
                obj_size -= sizeof(oopDesc) / oopSize;
                if (obj_size > 0 ) {
                  memset(to_zero, 0, obj_size * HeapWordSize);
                }
              }
          //根据是否启用偏向所来设置对象头信息
              if (UseBiasedLocking) {
                result->set_mark(ik->prototype_header());
              } else {
                result->set_mark(markOopDesc::prototype());
              }
              result->set_klass_gap(0);
              result->set_klass(k_entry);
              //将对象引用入栈,继续执行下一条指令
              SET_STACK_OBJECT(result, 0);
              UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1);
            }
          }
        }
        // Slow case allocation
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353