1)java虛擬機(jī)中對象的創(chuàng)建

??我們了解虛擬機(jī)內(nèi)存劃分的人,都知道對象的內(nèi)存分配幾乎都是在堆上的,這一點(diǎn)在java虛擬機(jī)規(guī)范中的描述是:所有的對象實(shí)例以及數(shù)組都會在堆上分配(但是隨著JIT編譯器的發(fā)展與逃逸分析技術(shù)逐漸成熟俱饿,棧上分配歌粥,標(biāo)量替換優(yōu)化技術(shù)將會導(dǎo)致一些變化,擦扯遠(yuǎn)了拍埠,所以所有的對象實(shí)例都在堆上分配就不是那么絕對了)

下面說虛擬機(jī)中對象的創(chuàng)建幾個步驟

  1. 類加載檢查
    ??虛擬機(jī)遇到new指令時失驶,首先會去檢查這個指令的參數(shù)是否能在常量池中定位到一個類的符號引用,并且檢查這個符號引用代表的類是否被裝載枣购、解析和初始化過嬉探。如果沒有那必須先執(zhí)行相應(yīng)的類的加載過程。
  2. 為對象分配內(nèi)存
    ??當(dāng)類加載成功后棉圈,類的對象的大小是確定了的涩堤。對象內(nèi)存的劃分等同于在堆里劃分出一塊指定大小的內(nèi)存。
    ??假設(shè)內(nèi)存是規(guī)整的分瘾,所有用過的內(nèi)存放在一邊胎围,空閑的放在另一邊,中間分界點(diǎn)有個指針芹敌,那分配內(nèi)存就是把指針向空閑區(qū)域方向挪動一段于對象大小相等的長度痊远,這種分配方式叫做“指針碰撞”(Bump the Pointer)垮抗。
    ??如果內(nèi)存不是規(guī)整的氏捞,那么就需要一個表來記錄,記錄哪些內(nèi)存是占用的冒版,哪些是空閑的液茎,那分配內(nèi)存就是在表里找到一塊足夠大的空間分配給對象實(shí)例,并更新這個表的記錄辞嗡,這種分配方式叫做“空閑列表”(Free List)捆等。
    ??選擇哪種分配方式與堆是否規(guī)整決定,而java堆是否規(guī)整又和垃圾收集器是否有壓縮整理功能決定栋烤。因此,在使用Serial挺狰、ParNew等帶有Compact過程的收集器時明郭,采用的分配方式是指針碰撞,而使用CMS這種基于Mark-Sweep算法的收集器時丰泊,采用的是空閑列表薯定。
    ??除了如何劃分內(nèi)存之外還有一個是我們需要考慮的問題,因?yàn)閖ava堆是線程共享的瞳购,那么多個線程同時操作堆上的內(nèi)存就會有問題话侄,比如正在給a對象分配內(nèi)存還沒來得及移動指針(或者是沒有修改空閑列表的記錄),這時對象b使用原來的指針來分配內(nèi)存,就會產(chǎn)生問題年堆。解決這個問題有兩種方式吞杭,一種是對分配內(nèi)存的動作進(jìn)行同步處理(實(shí)際上虛擬機(jī)采用CAS配上錯誤重試來保證分配內(nèi)存的原子性);另一種是采用線程間不共享的內(nèi)存來分配嘀韧,每個線程預(yù)先在java堆中分配一塊內(nèi)存篇亭,成為本地線程分配緩沖(Thread Local Allocation Buffer,TLAB )。哪個線程分配內(nèi)存就在該線程的TLAB上分配锄贷,只有在TLAB用完需要分配新的TLAB時译蒂,才需要同步鎖定。注:虛擬機(jī)是否使用TLAB谊却,可以通過-XX:+/-UseTLAB參數(shù)來設(shè)定柔昼。
  3. 內(nèi)存初始化
    ??內(nèi)存分配完后,需要把將分配到的內(nèi)存空間初始化為零值(不包換對象頭)炎辨,如果使用TLAB這一過程也可以提前至TLAB分配時進(jìn)行捕透。這一步操作保證了對象實(shí)例字段在java代碼中可以不賦初值就使用,程序能訪問到這些字段的數(shù)據(jù)類型所對應(yīng)的零值碴萧。
  4. 對象頭必要設(shè)置
    ??接下來虛擬機(jī)要對對象進(jìn)行必要的設(shè)置乙嘀,比如該對象是哪個類的實(shí)例、如何才能找到類的元數(shù)據(jù)信息破喻、對象的hash碼虎谢、對象的gc分代年齡等信息。這些信息均放在對象的對象頭(Object Header)中曹质。根據(jù)虛擬機(jī)當(dāng)前的運(yùn)行狀態(tài)的不同婴噩,如是否啟用偏向鎖等,對象頭會有不同的設(shè)置

總結(jié)
以上步驟完成后羽德,從虛擬機(jī)的角度來看几莽,一個新對象誕生了,但從java程序角度看宅静,一切才剛剛開始——init方法還沒有執(zhí)行章蚣,所有字段的數(shù)據(jù)類型都是對應(yīng)的零值。所以一般來說執(zhí)行new指令后會接著執(zhí)行init方法姨夹,把對象按照程序猿的意愿進(jìn)行初始化纤垂,這樣一個真正可以使用的對象才算完成。

下面的代碼是HotPot虛擬機(jī)bytecodeInterpreter.cpp的代碼片段

u2 index = Bytes::get_Java_u2(pc+1);
ConstantPool* constants = istate->method()->constants();
// 確保常量池中是已經(jīng)解釋的類
if (!constants->tag_at(index).is_unresolved_klass()) {
  // Make sure klass is initialized and doesn't have a finalizer
  // 確保類已經(jīng)初始化
  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;
  // 確保對象內(nèi)存已經(jīng)初始化
  if ( ik->is_initialized() && ik->can_be_fastpath_allocated() ) {
    // 取對象長度
    size_t obj_size = ik->size_helper();
    oop result = NULL;
    // If the TLAB isn't pre-zeroed then we'll have to do it
    // 如果TLAB沒有預(yù)先初始化那么need_zero為true后邊會進(jìn)行初始化
    bool need_zero = !ZeroTLAB;
    // 如果虛擬機(jī)啟用TLAB匀伏,那么在TLAB中分配對象
    if (UseTLAB) {
      result = (oop) THREAD->tlab().allocate(obj_size);
    }
    if (result == NULL) {
      need_zero = true;
      // Try allocate in shared eden
      // 嘗試在eden中分配對象
retry:
      HeapWord* compare_to = *Universe::heap()->top_addr();
      HeapWord* new_top = compare_to + obj_size;
      /*cmpxchg是x86中的CAS指令洒忧,這里是一個C++方法通過CAS方式分配空間,如果并發(fā)失敗够颠,轉(zhuǎn)到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) {
      // Initialize object (if nonzero size and need) and then the header
     // 如果需要熙侍,則為對象初始化零值
      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);
        }
      }
      // 根據(jù)是否啟用偏向鎖來設(shè)置對象頭信息
      if (UseBiasedLocking) {
        result->set_mark(ik->prototype_header());
      } else {
        result->set_mark(markOopDesc::prototype());
      }
      result->set_klass_gap(0);
      result->set_klass(k_entry);
     // 將對象引用入棧,繼續(xù)執(zhí)行下一條指令
      SET_STACK_OBJECT(result, 0);
      UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1);
    }
  }
}

相關(guān)文章:
java虛擬機(jī)中對象的創(chuàng)建
java虛擬機(jī)中對象的內(nèi)存布局
java虛擬機(jī)中對象的定位

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蛉抓,隨后出現(xiàn)的幾起案子庆尘,更是在濱河造成了極大的恐慌,老刑警劉巖巷送,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驶忌,死亡現(xiàn)場離奇詭異,居然都是意外死亡笑跛,警方通過查閱死者的電腦和手機(jī)付魔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來飞蹂,“玉大人几苍,你說我怎么就攤上這事〕卵疲” “怎么了妻坝?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長惊窖。 經(jīng)常有香客問我刽宪,道長,這世上最難降的妖魔是什么界酒? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任圣拄,我火速辦了婚禮,結(jié)果婚禮上盾计,老公的妹妹穿的比我還像新娘售担。我一直安慰自己赁遗,他們只是感情好署辉,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著岩四,像睡著了一般哭尝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上剖煌,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天材鹦,我揣著相機(jī)與錄音,去河邊找鬼耕姊。 笑死桶唐,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的茉兰。 我是一名探鬼主播尤泽,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了坯约?” 一聲冷哼從身側(cè)響起熊咽,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎闹丐,沒想到半個月后横殴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡卿拴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年衫仑,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片堕花。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡惑畴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出航徙,到底是詐尸還是另有隱情如贷,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布到踏,位于F島的核電站杠袱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏窝稿。R本人自食惡果不足惜楣富,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伴榔。 院中可真熱鬧纹蝴,春花似錦、人聲如沸踪少。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽援奢。三九已至兼犯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間集漾,已是汗流浹背切黔。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留具篇,地道東北人纬霞。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像驱显,于是被迫代替她去往敵國和親诗芜。 傳聞我的和親對象是個殘疾皇子侨舆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容