java jvm对象_Java对象在JVM中长啥样
前言
Java 是門面向對象的開發語言,那么我們自己編寫的 Java 類生成的對象是什么樣的?它肯定保存在虛擬機的內存中,但它以怎樣的結構來保存的呢?帶著疑問往下看看。
關于Klass
Java 層的開發可能不太熟悉 Klass,但肯定熟悉 class,我們只要知道 Klass 是 class 在 JVM 中的表示即可,即 Java class 對應 JVM Klass。C++ 中的繼承關系如下:
class MetaspaceObj
class Metadata
class Klass
Klass 類用來描述 Java 類信息,包括描述類型自身布局、類名、父類、子類、兄弟類等等。
關于oop
按前面 class 對應的方式,那么對象也應該有 JVM 內部與之相對應的表示吧?沒錯,就是 oop(ordinary object pointer),普通對象指針。它的定義如下:
typedef class oopDesc* oop;
其中 oopDesc 類是所有 oop 的基類。在 JVM 中,不同的 oop 用于描述特定類型的對象。比如類對象用 instanceOopDesc,數組用 arrayOopDesc。
Klass+oop模型
Java 對象在 JVM 中的結構如下,包括 header 和對象內容。如下圖中,左邊的是 instanceOopDesc,即一般的類對象,header 包括了標識和元數據,標識用于存儲運行時記錄信息,包括哈希碼、GC鎖和線程鎖等等。而右邊的為 arrayOopDesc,即數組對象,header 多了個 length,用于記錄數組長度。
來個demo
public class Test {
private String[] flag = { "a", "b", "c" };
private String name = "test";
public static void main(String[] args) throws Exception {
Test test = new Test();
String _name = "test";
System.out.println(test.flag);
System.out.println(_name);
}
}
查看 main 線程的棧內存,我們主要是要拿到 Test 對象的地址,即0x000000008a105dd0。
接著用 inspector 來查看0x000000008a105dd0地址對應的 oop,看到這個 oop 就是我們的 Test 類生成的對象結構了,包含了 mark 和 metadata。這里可能會有個疑問,就是前面不是說數組還有一個 length 來表示數組長度的嗎?但圖中的 flag 數組變量并沒有看到 length 啊。
其實數組 oop 并不是沒有 length,而是 C++ 并沒有聲明這個變量,而是通過指針來直接將數組長度保存到對應的內存了,所以這里是看不到的。通過下面具體的實現代碼就能清楚了解到原因了。是不是我們就沒辦法看到這個長度值呢?并不是,下面繼續看如何來看這個值。
int length() const {
return *(int*)(((intptr_t)this) + length_offset_in_bytes());
}
void set_length(int length) {
*(int*)(((intptr_t)this) + length_offset_in_bytes()) = length;
}
前面我們可以得到 flag 數組 oop 的地址為0x000000008a105de8。64位機器上_mark為8字節,_metadata為4字節,那么將地址加12,得到0x000000008a105df4。然后用 hsdb 命令行的 examine 得到地址的值,得到0x8a105e0800000003,其中00000003便是。
原文作者:超人汪小建
總結
以上是生活随笔為你收集整理的java jvm对象_Java对象在JVM中长啥样的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 来电模式设置,andro
- 下一篇: 银行界加强计算机病毒管理,银行计算机管理