前言
在《openjdk的啓動流程》一文,create_vm方法中
initialize_class(vmSymbols::java_lang_Thread(), CHECK_0);//裝載threadClass
oop thread_object = create_initial_thread(thread_group, main_thread, CHECK_0);//創建第一個thread對象
在《JVM內存模型》中探討過,Java對象在內存中是實例數據和類型數據相分離的,實例數據保存了一個指向類型數據的指針,而虛擬機中用oop-klass二分模型很好的進行實現 。
二分模型
Oop表示Java實例,主要用於表示實例數據,不提供任何虛函數功能,Oop保存了對應Kclass的指針,所有方法調用通過Klass完成並通過Klass獲取類型信息,Klass基於C++的虛函數提供對Java多態的支持。Klass作爲父類主要職責是描述了類的繼承關係。
klass
MetaspaceObj #類是作爲存放在Metaspace元空間的中類的基類
└───Metadata #內部表示類相關元數據的一個基類
│ └───Klass #普通類模板
│ │ └───ArrayKlass #數組類模板
│ │ │ └───TypeArrayKlass #基本類型數組
│ │ │ └───ObjArrayKlass #類數組或者多維數組
│ │ └───InstanceKlass #類實例
│ │ │ └───InstanceClassLoaderKlass #加載器類實例
│ │ │ └───InstanceMirrorKlass #監控類實例
│ │ │ └───InstanceRefKlass #引用類實例
/**---------------Klass------------------**/
//如果不是InstanceKlass或者ArrayKlass,則該值爲0
//對InstanceKclass而言,該值表示對象的以字節爲單位的內存佔用空間
//對ArrayKlass而言,該值是一個組合起來的假數字,包含4部分,具體怎麼組合和解析由子類實現:
// tag:如果數組元素是對象實例則是0x80,否則是0xC0
// hsz: 數組頭元素的字節數
// ebt:數組元素的類型,枚舉值BasicType
// esz:數組元素大小,以字節爲單位
//該值因爲被頻繁查詢,所以放在虛函數表指針的後面。
jint _layout_helper;
//用於快速定位的父類
//如果此klass表示的是接口,則定位到&_secondary_super_cache
//如果此klass表示的是類,則定位到&_primary_supers[depth()],就是_primary_supers的最後一位
juint _super_check_offset;
//類名.
//Instance classes: java/lang/String,
//Array classes: [I,[Ljava/lang/String;
//Set to zero for all other kinds of classes.
Symbol* _name;
// Klass指針,上一次查找過的接口
Klass* _secondary_super_cache;
//所有接口的接口
Array<Klass*>* _secondary_supers;
//默認繼承的類列表,如Object
Klass* _primary_supers[_primary_super_limit];
// java/lang/Class 的實例 mirroring this class
oop _java_mirror;
// 父類
Klass* _super;
// First subclass (NULL if none); _subklass->next_sibling() is next one
//子類頭節點
Klass* _subklass;
// Sibling link (or NULL); links all subklasses of a klass
//串連所有子類,形成鏈表
Klass* _next_sibling;
// All klasses loaded by a class loader are chained through these links
//ClassLoader加載的下一個Klass
Klass* _next_link;
//此類對應的ClassLoader
ClassLoaderData* _class_loader_data;
//修改標識,Class.getModifiers使用
jint _modifier_flags;
//獲取類的修飾符,如private類訪問控制,final,static,abstract ,native等
AccessFlags _access_flags;
/**---------------Klass------------------**/
/**---------------InstanceKlass------------------**/
//該類使用的所有註解
Annotations* _annotations;
//該類的數組Klass
Klass* _array_klasses;
// 類的常量池
ConstantPool* _constants;
//內部類
//The InnerClasses attribute and EnclosingMethod attribute.
//If the class has InnerClasses attribute
//1.inner_class_info_index
//2.outer_class_info_index
//3.inner_name_index
//4.inner_class_access_flags
//If the EnclosingMethod attribute exists,
//1.class_index
//2.method_index
//If only the InnerClasses attribute exists
// the _inner_classes array length is number_of_inner_classes * 4.
// If the class has both InnerClasses and EnclosingMethod attributes
//the _inner_classes array length is number_of_inner_classes * 4 + enclosing_method_attribute_size.
Array<jushort>* _inner_classes;
// the source debug extension for this klass, NULL if not specified.
// Specified as UTF-8 string without terminating zero byte in the classfile,
// it is stored in the instanceklass as a NULL-terminated UTF-8 string
char* _source_debug_extension;
//根據類名計算的以該類的數組的名字
Symbol* _array_name;
//非靜態字段的內存大小,以heapOopSize爲單位,默認使用壓縮指針時heapOopSize是int的大小
// Number of heapOopSize words used by non-static fields in this klass
// (including inherited fields but after header_size()).
int _nonstatic_field_size;
//靜態字段的內存大小,以字寬(HeapWordSize,實際是一個指針變量的內存大小)爲單位
// number words used by static fields (oop and non-oop) in this klass
int _static_field_size;
//Generic signature在常量池中的索引
// Constant pool index to the utf8 entry of the Generic signature, or 0 if none.
u2 _generic_signature_index;
//包含此類的源文件名在常量池中索引
// Constant pool index to the utf8 entry for the name of source file
// containing this klass, 0 if not specified.
u2 _source_file_name_index;
//此類的包含的靜態引用類型字段的數量
// number of static oop fields in this klass
u2 _static_oop_field_count;
//總的字段數量
// The number of declared Java fields
u2 _java_fields_count;
//非靜態的oop map block的內存大小,以字寬爲單位 (oop根據這個來申請內存)
//size in words of nonstatic oop map blocks
int _nonstatic_oop_map_size;
//minor version number of class file
u2 _minor_version;
//major version number of class file
u2 _major_version;
//初始化的此類Thread指針
// Pointer to current thread doing initialization (to handle recusive initialization)
Thread* _init_thread;
// Java 虛函數表(vtable)的內存大小,以字寬爲單位
int _vtable_len;
// Java 接口函數表(itable)的內存大小,以字寬爲單位
int _itable_len;
// OopMapCache for all methods in the klass (allocated lazily)
OopMapCache* volatile _oop_map_cache;
//MemberNameTable指針,保存了成員名
MemberNameTable* _member_names;
//NIid指針,該類的第一個靜態字段的JNIid,可以根據其_next屬性獲取下一個字段的JNIid
JNIid* _jni_ids;
//jmethodID指針,java方法的ID列表
jmethodID* _methods_jmethod_ids;
//依賴的本地方法,以根據其_next屬性獲取下一個nmethod
nmethodBucket* _dependencies;
//棧上替換的本地方法鏈表的頭元素
nmethod* _osr_nmethods_head;
//bpt lists, managed by Method*
BreakpointInfo* _breakpoints;
//class文件的內容,JVMTI retransform時使用
// JVMTI fields can be moved to their own structure - see 6315920
// JVMTI: cached class file, before retransformable agent modified it in CFLH
JvmtiCachedClassFileData* _cached_class_file;
//JVMTI: used during heap iteration
JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map;
//已經分配的方法的idnum的個數,可以根據該ID找到對應的方法,如果JVMTI有新增的方法,已分配的ID不會變
// JNI/JVMTI: increments with the addition of methods, old ids don't change
volatile u2 _idnum_allocated_count;
//類的狀態,是一個枚舉值ClassState,
//allocated(已分配內存),
//loaded(從class文件讀取加載到內存中),
//linked(已經成功鏈接和校驗),
//being_initialized(正在初始化),
//fully_initialized(已經完成初始化),
//initialization_error(初始化異常)
u1 _init_state;
//引用類型
u1 _reference_type;
// 方法指針數組,類方法
Array<Method*>* _methods;
// 從接口繼承的默認方法
Array<Method*>* _default_methods;
// 直接實現的接口Klass
Array<Klass*>* _local_interfaces;
// 所有實現的接口Klass,包含_local_interfaces和通過繼承間接實現的接口
Array<Klass*>* _transitive_interfaces;
// 保存類中方法聲明時的順序,JVMTI使用
Array<int>* _method_ordering;
//默認方法在虛函數表中的索引
// Int array containing the vtable_indices for default_methods
// offset matches _default_methods offset
Array<int>* _default_vtable_indices;
// Instance and static variable information, starts with 6-tuples of shorts
// [access, name index, sig index, initval index, low_offset, high_offset]
// for all fields, followed by the generic signature data at the end of
// the array. Only fields with generic signature attributes have the generic
// signature data set in the array. The fields array looks like following:
//
// f1: [access, name index, sig index, initial value index, low_offset, high_offset]
// f2: [access, name index, sig index, initial value index, low_offset, high_offset]
// ...
// fn: [access, name index, sig index, initial value index, low_offset, high_offset]
// [generic signature index]
// [generic signature index]
// offset = int(high_offset,low_offset) >> 2
// |---------high---------|---------low---------|
// ..........................................00 - blank
// [------------------offset----------------]01 - real field offset
// ......................[-------type-------]10 - plain field with type
// [--contention_group--][-------type-------]11 - contended field with type and contention group
Array<u2>* _fields;
//接下來幾個屬性是內嵌的在類中的,沒有對應的屬性名,只能通過指針和偏移量的方式訪問:
// embedded Java vtable follows here,Java虛函數表,大小等於_vtable_len
// embedded Java itables follows here,Java接口函數表,大小等於 _itable_len
// embedded static fields follows here
// embedded nonstatic oop-map blocks follows here,非靜態oop-map blocks ,大小等於_nonstatic_oop_map_size
// embedded implementor of this interface follows here
//(接口的實現類,僅當前類表示一個接口時存在,如果接口沒有任何實現類則爲NULL,如果只有一個實現類則爲該實現類的Klass指針,如果有多個實現類,爲當前類本身)
// The embedded implementor only exists if the current klass is an
// iterface. The possible values of the implementor fall into following
// three cases:
// NULL: no implementor.
// A Klass* that's not itself: one implementor.
// Itself: more than one implementors.
// embedded host klass follows here
//(只在匿名類中存在,爲了支持JSR 292中的動態語言特性,會給匿名類生成一個host klass)
// The embedded host klass only exists in an anonymous class for
// dynamic language support (JSR 292 enabled). The host class grants
// its access privileges to this class also. The host class is either
// named, or a previously loaded anonymous class. A non-anonymous class
// or an anonymous class loaded through normal classloading does not
// have this embedded field.
/**---------------InstanceKlass------------------**/
Oop
oopDesc #內部實例基類
└───arrayOopDesc #內部表示類相關元數據的一個基類
│ └───objArrayOopDesc #普通類模板
│ └───typeArrayOopDesc #基本類型數組
└───instanceOopDesc #加載器類實例
└───markOopDesc #用於描述對象頭
/**---------------oopDesc------------------**/
//markOopDesc是oopDesc的子類,用於描述對象頭,因爲保證對象狀態變更在各CPU種同步,所以加volatile修飾
volatile markOop _mark;
//是一個union結構,用於表示該oopDesc關聯的Klass,使用壓縮指針時,就設置其中的_compressed_klass屬性
union _metadata {
Klass* _klass;
narrowKlass _compressed_klass;
} _metadata;
// BarrierSet提供了屏障實現和系統其它部分之間的接口,是靜態屬性,必須初始化
static BarrierSet* _bs;
/**---------------oopDesc------------------**/
/**---------------markOopDesc------------------**/
//markOopDesc繼承自oopDesc,用於描述對象頭,
//oopDesc中的_mark屬性引用的並不是一個真實存在的markOopDesc實例,它是一個32位的數組(啓用指針壓縮)或者64位數組(禁止指針壓縮)
//注意指針壓縮包含兩種,Java對象類型字段的oop指針和oopDesc引用Klass的指針,分別對應兩個參數UseCompressedOops和UseCompressedClassPointers
//
// 32 bits:
// --------
// hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)
// JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object)
// size:32 ------------------------------------------>| (CMS free block)
// PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
//
// 64 bits:
// --------
// unused:25 hash:31 -->| unused:1 age:4 biased_lock:1 lock:2 (normal object)
// JavaThread*:54 epoch:2 unused:1 age:4 biased_lock:1 lock:2 (biased object)
// PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
// size:64 ----------------------------------------------------->| (CMS free block)
//
// unused:25 hash:31 -->| cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && normal object)
// JavaThread*:54 epoch:2 cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && biased object)
// narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)
// unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)
/**---------------markOopDesc------------------**/
/**---------------instanceOopDesc------------------**/
//instanceOopDesc繼承自oopDesc,用於表示普通的Java對象,每次new一個Java對象就會創建一個新的instanceOopDesc實例。
//該類沒有添加新的屬性,只是新增了兩個方法.
//用於返回包含OopDesc自身屬性的內存的偏移量,即該偏移量之後的內存用於保存Java對象實例屬性
base_offset_in_bytes()
//用於判斷是否包含指定偏移量的非靜態屬性。
contains_field_offset(int offset, int nonstatic_field_size)
//instanceOopDesc是如何保存Java對象實例的屬性了?
//基本類型字段的實現都是在oopDesc的地址的基礎上加上一個偏移量算出該字段的地址,偏移量的單位是字節,各字段的偏移量和初始值等屬性都保存在InstanceKlass的_fields屬性中,根據該地址可以直接獲取或者設置字段值
/**---------------instanceOopDesc------------------**/
/**---------------arrayOopDesc------------------**/
// arrayOopDesc繼承自oopDesc,該類是所有數組OopDesc的基類,arrayOopDesc同InstanceOopDesc的內存佈局是不一樣的,除OopDesc定義的屬性外還需保存數組的長度,數組元素的取值。
//該類添加了幾個跟數組相關的方法,如下:
//獲取首元素的偏移量
int base_offset_in_bytes(BasicType type)
//獲取首元素的地址
void* base(BasicType type)
//index是否數組越界
bool is_within_bounds(int index)
//獲取數組的長度
int length()
//設置數組長度
void set_length(int length)
//獲取數組的最大長度
int32_t max_array_length(BasicType type):
//從代碼可知數組長度保存在_metadata屬性的後面,類型爲int,佔4字節,這也決定了數組的最大長度不能超過int的最大值。
/**---------------arrayOopDesc------------------**/
/**---------------typeArrayOopDesc------------------**/
//typeArrayOopDesc繼承自arrayOopDesc,用於表示數組元素是基本類型如int,long等的數組。跟InstanceOopDesc類似
/**---------------typeArrayOopDesc------------------**/
/**---------------objArrayOopDesc------------------**/
//objArrayOopDesc繼承自arrayOopDesc,用於表示元素是對象的數組,包括多維數組。同typeArrayOopDesc,該類增加了根據索引獲取和設置數組的方法,同樣需要根據配置對指針做壓縮解壓縮處理
/**---------------objArrayOopDesc------------------**/
案例材料
- 實驗類
package mm;
interface A{
void showA();
}
interface B{
String WWTXT = "khkh";
void showB();
}
class BaseClass implements B {
private int b;
public BaseClass(int b) {
this.b = b;
}
@Override
public void showB() {
System.out.println(b);
}
}
public class MyTest extends BaseClass implements A{
public static String TXT = "yoyo";
public static String getTXT(){
return TXT+"@bbb";
}
private int a;
private String s;
public MyTest(int a,int b) {
super(b);
this.a = a;
this.s = "test";
}
public static void main(String[] args) {
MyTest t = new MyTest(6,7);
MyTest[] gg = new MyTest[2];
gg[0] = t;
t.showA();
t.showB();
System.out.println(gg.getClass());
System.out.println(t.hashCode());
System.out.println(WWTXT);
System.out.println(getTXT());
System.out.println("end");
}
@Override
public void showA() {
System.out.println(a);
}
}
- 運行結果
6
7
class [Lmm.MyTest;
1227229563
khkh
yoyo@bbb
- sa命令
sudo java -cp .:$JAVA_HOME/lib/sa-jdi.jar sun.jvm.hotspot.HSDB
《Hotspot學習利器:HSDB和CLHSDB》
- 查看分區情況
universe
ParallelScavengeHeap [
PSYoungGen
[ eden = [0x0000000174380000,0x00000001746199d8,0x0000000176400000] ,
from = [0x0000000176900000,0x0000000176900000,0x0000000176e00000] ,
to = [0x0000000176400000,0x0000000176400000,0x0000000176900000]
]
PSOldGen [ [0x000000011ee00000,0x000000011ee00000,0x0000000124380000] ] ]
- 在eden中搜索mm.MyTest對象
scanoops 0x0000000174380000 0x0000000176400000 mm.MyTest
0x00000001745a6648 mm/MyTest
- 查看對象的具體數據
#因爲我在JAVA類啓動的時,採用-XX:-UseCompressedOops,禁用壓縮格式
mem 0x00000001745a6648 8
#對照instanceOopDesc結構得
0x00000001745a6648: 0x0000004926097b01 # mark地垃
0x00000001745a6650: 0x00000001a3cad5f8 # intanceKlass地址
0x00000001745a6658: 0x0000000000000007 # 數據實例7
0x00000001745a6660: 0x0000000000000006 # 數據實例6
0x00000001745a6668: 0x00000001745a6670 # “s”字符串對象地址
0x00000001745a6670: 0x0000000000000001
0x00000001745a6678: 0x00000001a38b5058
0x00000001745a6680: 0x00000001745a6690
# mark的驗證
t對象處理於無狀態,又走不壓縮格式,其mark對應是格式應該是
unused:25 hash:31 -->| unused:1 age:4 biased_lock:1 lock:2 (normal object)
4926097b轉爲10進制就是1227229563,和我們輸入的t.hashCode對應
#intanceKlass驗證
class mm.MyTest
mm/MyTest @0x00000001a3cad5f8
#保用class命令找到類的結果和我們的一樣。。
#結合的例子<成員>中查看field信息得到offset
#實例對象地址加offset就得到成員數據信息
# 其中靜態變量的數據不存在實例中,而在類對象中
# 類對象地址(_java_mirror)加offset就得到靜態成員數據信息
oop Klass::_java_mirror: Oop for java/lang/Class @ 0x00000001745a57e8
- 數組對象
# 因爲數組gg對象用class的方式找不到,可以通過運行時的本地變量找過去
# 保使用thread <main進程ID> 查看main進程stack,Stack in use by Java,再根據mem命令去
# 或者 直接用ui提供的 stack for memory for main(推薦使用,右邊有直接內存值說明)
# 在2是你查以很快找到內容說明爲ObjArray的字樣找到其地址
mem 0x00000001745a6930 5
0x00000001745a6930: 0x0000000000000001 #mark
0x00000001745a6938: 0x00000001a3cae208 #對應的[Lmm.MyTest
0x00000001745a6940: 0x0000000000000002 #數據長度
0x00000001745a6948: 0x00000001745a6648 #第一mm.MyTest的指針
0x00000001745a6950: 0x0000000000000000 #第二個爲null
- 類名,父類,接口
#查看類名
inspect 0x00000001a3cad5f8
Symbol* Klass::_name: Symbol @ 0x00007faa92e00040
mem 0x00007faa92e00040 3
0x00007faa92e00040: 0x08e1dfb100020009
0x00007faa92e00048: 0x736554794d2f6d6d
0x00007faa92e00050: 0x00746e6500000074
Symbol(繼承自MetaspaceObj){
unsigned short _length // 16bits,名字長度,這裏是0009
volatile short _refcount, // 16bits,0002
int _identity_hash; // 32bits,08e1dfb1
//具體類名,長度爲0009*2,爲74736554794d2f6d6d,
jbyte _body[1];
}
#使用以這代碼
private static String hexToAscii(String hexStr) {
StringBuilder output = new StringBuilder("");
for (int i = 0; i < hexStr.length(); i += 2) {
String str = hexStr.substring(i, i + 2);
output.append((char) Integer.parseInt(str, 16));
}
return output.toString();
}
#得tseTyM/mm
#查看父類
Klass* Klass::_super: Klass @ 0x00000001a3cad3b8
#用同上方法查看名字爲:ssalCesaB/mm
#查看接口
Array<Klass*>* InstanceKlass::_local_interfaces: Array<Klass*> @ 0x00000001a3cac420
#用同上方法查看名字爲:A/mm
- 成員
#獲取其中field信息
Array<u2>* InstanceKlass::_fields: Array<u2> @ 0x00000001a3cac7a0
mem 0x00000001a3cac7a0 6 #查看內存對應的信息
# 最前面4個字節爲Array的頭信息
# 6*2字節爲一組
#[access, name index, sig index, initial value index, low_offset, high_offset]
# offset = int(high_offset,low_offset) >> 2
0x00000001a3cac7a0: 0x001d000900000012#00000012爲頭信息
0x00000001a3cac7a8: 0x000002810000001e#offset=160,name=001d
0x00000001a3cac7b0: 0x00000020001f0002
0x00000001a3cac7b8: 0x0021000200000061#offset=24,name=001f
0x00000001a3cac7c0: 0x000000810000001e#offset=32,name=0021
0x00000001a3cac7c8: 0x0000000000000000
#結合的例子<常量池>得
001d=TXT
001f=a
0021=s
- 常量池
#獲取其中_constants信息
ConstantPool* InstanceKlass::_constants: ConstantPool @ 0x00000001a3cac098
class ConstantPool(繼承自MetaspaceObj){
// the tag array describing the constant pool's contents
//常量池數據標記Constant Type
Array<u1>* _tags;
// the cache holding interpreter runtime information
//運行時緩存
ConstantPoolCache* _cache;
// the corresponding class
//哪個類的常量池
InstanceKlass* _pool_holder;
//for variable-sized (InvokeDynamic) nodes, usually empty
//常量池的值 Constant Value
Array<u2>* _operands;
// Array of resolved objects from the constant pool and map from resolved
// object index to original constant pool index
//已經解析過的引用
jobject _resolved_references;
Array<u2>* _reference_map;
#打印常量池
print 0x00000001a3cac098
Holder Class
public class mm.MyTest @0x00000001a3cad5f8
Constants
Index Constant Type Constant Value
1 JVM_CONSTANT_Class public final class java.lang.StringBuilder @0x00000001a3936e90
2 JVM_CONSTANT_Methodref #1 #58
3 JVM_CONSTANT_Fieldref #11 #59
4 JVM_CONSTANT_Methodref #1 #60
5 JVM_CONSTANT_String "@bbb"
6 JVM_CONSTANT_Methodref #1 #62
7 JVM_CONSTANT_Methodref #27 #63
8 JVM_CONSTANT_Fieldref #11 #64
9 JVM_CONSTANT_String "test"
...
20 JVM_CONSTANT_UnresolvedClass mm/B
21 JVM_CONSTANT_String "khkh"
22 JVM_CONSTANT_Methodref #75 #81
23 JVM_CONSTANT_Methodref #11 #82
24 JVM_CONSTANT_String "end"
25 JVM_CONSTANT_Methodref #27 #70
26 JVM_CONSTANT_String "yoyo"
27 JVM_CONSTANT_Class class mm.BaseClass @0x00000001a3cad3b8
28 JVM_CONSTANT_UnresolvedClass mm/A
29 JVM_CONSTANT_Utf8 "TXT"
30 JVM_CONSTANT_Utf8 "Ljava/lang/String;"
31 JVM_CONSTANT_Utf8 "a"
32 JVM_CONSTANT_Utf8 "I"
33 JVM_CONSTANT_Utf8 "s"
...
#結合的例子<成員>得
001d=29=TXT
001f=31=a
0021=33=s
- 方法
#查看類方法
Array<Method*>* InstanceKlass::_methods: Array<Method*> @ 0x00000001a3cac7d0
#Array頭對象信息佔8字節,我們直接
mem 0x00000001a3cac7d8 6
0x00000001a3cac7d8: 0x00000001a3cac920 #<init>
0x00000001a3cac7e0: 0x00000001a3cacc08 #<clinit>
0x00000001a3cac7e8: 0x00000001a3caca28 #main()
0x00000001a3cac7f0: 0x00000001a3cacb70 #showB()
0x00000001a3cac7f8: 0x00000001a3cacad0 #showA()
0x00000001a3cac800: 0x00000001a3cac858 #getTXT
#打印showA方法
print 0x00000001a3cacad0
public void showA() @0x00000001a3cacad0
Holder Class
public class mm.MyTest @0x00000001a3cad5f8
Bytecode
line bci bytecode
60 0 getstatic #15 [Field java.io.PrintStream out] of public final class java.lang.System @0x00000001a38c95d8
60 3 aload_0
60 4 getfield #8 [Field int a] [fast_igetfield] of public class mm.MyTest @0x00000001a3cad5f8
60 7 invokevirtual #19 [Method void println(int)] of public class java.io.PrintStream @0x00000001a3a1fbd0
61 10 return
#Methnd的結構(繼承自MetaspaceObj)
// |------------------------------------------------------|
// | header |
// | klass |
// |------------------------------------------------------|
// | ConstMethod* (oop) |
// |------------------------------------------------------|
// | methodData (oop) |
// | methodCounters |
// |------------------------------------------------------|
// | access_flags |
// | vtable_index |
// |------------------------------------------------------|
// | result_index (C++ interpreter only) |
// |------------------------------------------------------|
// | method_size | intrinsic_id| flags |
// |------------------------------------------------------|
// | code (pointer) |
// | i2i (pointer) |
// | adapter (pointer) |
// | from_compiled_entry (pointer) |
// | from_interpreted_entry (pointer) |
// |------------------------------------------------------|
// | native_function (present only if native) |
// | signature_handler (present only if native) |
// |------------------------------------------------------|
主要參考
《hotspot實戰》
《Hotspot Oop模型——Java對象內存表示機制》
《Hotspot Klass模型——Java類內存表示機制》