《深入理解 Java 虛擬機》讀書筆記:類文件結(jié)構(gòu)

正文

一方庭、無關(guān)性的基石

1翩瓜、兩種無關(guān)性

  • 平臺無關(guān)性: Java 程序的運行不受計算機平臺的限制跨扮,“一次編寫序无,到處運行”。
  • 語言無關(guān)性: Java 虛擬機只與 Class 文件關(guān)聯(lián)衡创,并不關(guān)心 Class 文件的來源是何種語言帝嗡。

2、無關(guān)性的實現(xiàn)基礎(chǔ)

  • 各種不同平臺的虛擬機
  • 所有平臺都統(tǒng)一使用的字節(jié)碼存儲格式

二璃氢、Class 類文件的結(jié)構(gòu)

Class 類文件是一組以 8 字節(jié)為基礎(chǔ)單位的二進制流哟玷,各個數(shù)據(jù)項目嚴(yán)格按照順序緊湊地排列在 Class 文件中,中間沒有添加任何分隔符一也。當(dāng)遇到需要占用 8 字節(jié)以上空間的數(shù)據(jù)項目時巢寡,則按照高位在前(最高位字節(jié)在地址最低位)的方式分割成若干個 8 位字節(jié)進行存儲。

Class 文件格式采用一種類似 C 語言結(jié)構(gòu)體的偽結(jié)構(gòu)來存儲數(shù)據(jù)塘秦,這種偽結(jié)構(gòu)中只有兩種數(shù)據(jù)類型:無符號數(shù)和表讼渊。

  • 無符號數(shù): 基本數(shù)據(jù)類型,以 u1尊剔、u2爪幻、u4、u8 來分別代表 1 個字節(jié)、2 個字節(jié)挨稿、4 個字節(jié)和 8 個字節(jié)的無符號數(shù)仇轻。可用來描述數(shù)字奶甘、索引引用篷店、數(shù)量值或按照 UTF-8 編碼構(gòu)成字符串值。
  • 表: 由多個無符號數(shù)或其他表作為數(shù)據(jù)項構(gòu)成的復(fù)合數(shù)據(jù)類型臭家,所有表都習(xí)慣性地以“_info”結(jié)尾疲陕。表用于描述有層次關(guān)系的復(fù)合結(jié)構(gòu)數(shù)據(jù),整個 Class 文件本質(zhì)上就是一張表钉赁。

無論是無符號數(shù)還是表蹄殃,當(dāng)需要描述同一類型但數(shù)量不定的多個數(shù)據(jù)時,會使用一個前置的容量計數(shù)器加若干個連續(xù)數(shù)據(jù)項的形式你踩,這若干個連續(xù)數(shù)據(jù)項稱為集合诅岩。

Class 文件格式:

類型 名稱 數(shù)量
u4 magic(魔數(shù)) 1
u2 minor_version(次版本號) 1
u2 major_version(主版本號) 1
u2 constant_pool_count(常量池容量計數(shù)器) 1
cp_info constant_pool(常量池) constant_pool_count - 1
u2 access_flags(訪問標(biāo)志) 1
u2 this_class(類索引) 1
u2 super_class(父類索引) 1
u2 interfaces_count(接口計數(shù)器) 1
u2 interfaces(接口索引集合) interfaces_count
u2 fields_count(字段表計數(shù)器) 1
field_info fields(字段表集合) fields_count
u2 methods_count(方法表計數(shù)器) 1
method_info methods(方法表集合) methods_count
u2 attributes_count(屬性表計數(shù)器) 1
attribute_info attributes(屬性表集合) attributes_count

1、魔數(shù)

每個 Class 文件的頭 4 個字節(jié)稱為魔數(shù)带膜,用于確定該文件是否為一個能被虛擬機接受的 Class 文件吩谦。其值為:0xCAFEBABE(咖啡寶貝?)膝藕。

2式廷、Class 文件的版本

緊接著魔數(shù)的 4 個字節(jié)存儲的是 Class 文件的版本號:第 5、6 個字節(jié)是次版本號束莫,第 7懒棉、8 個字節(jié)是主版本號。

3览绿、常量池

緊接著主次版本號之后的是常量池入口,常量池可以理解為 Class 文件中的資源倉庫穗慕。

由于常量池中常量的數(shù)量是不固定的饿敲,所以在常量池入口放置了一個 u2 類型的常量池容量計數(shù)器。該計數(shù)器的索引值是從 1 而不是從 0 開始逛绵,當(dāng)表示“不引用任何一個常量池項目”時怀各,則可將計數(shù)器置為 0。

常量池主要存放兩大類常量:字面量和符號引用术浪。每一項常量都是一個表瓢对,這些表開始的第一位是一個 u1 類型的標(biāo)志位,代表當(dāng)前常量所屬的常量類型胰苏。常量池目前有 14 種常量類型硕蛹,它們各自均有自己的結(jié)構(gòu)。

常量池的項目類型:

類型 標(biāo)志 描述
CONSTANCT_Utf8_info 1 UTF-8 編碼的字符串
CONSTANCT_Integer_info 3 整型字面量
CONSTANCT_Float_info 4 浮點型字面量
CONSTANCT_Long_info 5 長整型字面量
CONSTANCT_Double_info 6 雙精度浮點型字面量
CONSTANCT_Class_info 7 類或接口的符號引用
CONSTANCT_String_info 8 字符串類型字面量
CONSTANCT_Fieldref_info 9 字段的符號引用
CONSTANCT_Methodref_info 10 類中方法的符號引用
CONSTANCT_InterfaceMethodref_info 11 接口中方法的符號引用
CONSTANCT_NameAndType_info 12 字段或方法的部分符號引用
CONSTANCT_MethodHandle_info 15 表示方法句柄
CONSTANCT_MethodType_info 16 標(biāo)識方法類型
CONSTANCT_InvokeDynamic_info 18 表示一個動態(tài)方法調(diào)用點

常量類型結(jié)構(gòu):

(1)CONSTANT_Class_info 類型常量

類型 名稱 數(shù)量 描述
u1 tag 1 標(biāo)志位,值為 0x07
u2 name_index 1 索引值法焰,指向常量池中一個 CONSTANT_Utf8_info 類型常量秧荆,表示這個類(或接口)的全限定名

(2)CONSTANT_Utf8_info 類型常量

類型 名稱 數(shù)量 描述
u1 tag 1 標(biāo)志位,值為 0x01
u2 length 1 UTF-8 編碼的字符串占用的字節(jié)數(shù)
u1 bytes length 長度為 length 的 UTF-8 編碼的字符串

(3)...

4埃仪、訪問標(biāo)志

常量池之后乙濒,緊接著的兩個字節(jié)代表訪問標(biāo)志,用于識別一些類或接口層次的訪問信息卵蛉,包括:這個 Class 是類還是接口颁股、是否定義為 public 類型、是否定義為 abstract 類型傻丝、是否被聲明為 final(只有類可設(shè)置)等甘有。

訪問標(biāo)志:

標(biāo)志名稱 標(biāo)志值 含義
ACC_PUBLIC 0x0001 是否為 public 類型
ACC_FINAL 0x0010 是否被聲明為 final,只有類可設(shè)置
ACC_SUPER 0x0020 是否允許使用 invokespecial 字節(jié)碼指令的新語意桑滩,invokespecial 指令的語意在 JDK1.0.2 發(fā)生過改變梧疲,為了區(qū)別使用哪種語意,JDK1.0.2 之后編譯出來的類的這個標(biāo)志都必須為真
ACC_INTERFACE 0x0200 標(biāo)識這個一個接口
ACC_ABSTRACT 0x0400 是否為 abstract 類型
ACC_SYNTHETIC 0x1000 標(biāo)識這個類并非由用戶代碼產(chǎn)生
ACC_ANNOTATION 0x2000 標(biāo)識這是一個注解
ACC_ENUM 0x4000 標(biāo)識這是一個枚舉

5运准、類索引幌氮、父類索引與接口索引集合

類索引和父類索引都是 u2 類型的數(shù)據(jù),而接口索引集合是一組 u2 類型的數(shù)據(jù)的集合胁澳,Class 文件由這三項數(shù)據(jù)確定這個類的繼承關(guān)系该互。

  • 類索引:指向一個類型為 CONSTANT_Class_info 的類描述符常量,表示該類的全限定名韭畸。
  • 父類索引:指向一個類型為 CONSTANT_Class_info 的類描述符常量宇智,表示父類的全限定名。
  • 接口索引集合:用于描述該類實現(xiàn)了哪些接口胰丁,接口索引集合的入口放置了一個 u2 類型的接口計數(shù)器随橘,表示索引表的容量。

6锦庸、字段表集合

字段表用于描述接口或類中聲明的變量机蔗。字段包括類級變量以及實例變量,但不包括在方法內(nèi)部聲明的局部變量甘萧。

字段表結(jié)構(gòu):

類型 名稱 數(shù)量
u2 access_flags(字段訪問標(biāo)志) 1
u2 name_index(簡單名稱索引) 1
u2 descriptor_index(描述符索引) 1
u2 attributes_count(屬性表計數(shù)器) 1
attribute_info attributes(屬性表集合) attributes_count
  • 字段訪問標(biāo)志(access_flags):
標(biāo)志名稱 標(biāo)志值 含義
ACC_PUBLIC 0x0001 字段是否 public
ACC_PRIVATE 0x0002 字段是否 private
ACC_PROTECTED 0x0004 字段是否 protected
ACC_STATIC 0x0008 字段是否 static
ACC_FINAL 0x0010 字段是否 final
ACC_VOLATILE 0x0040 字段是否 volatile
ACC_TRANSIENT 0x0080 字段是否 transient
ACC_SYNTHETIC 0x1000 字段是否由編譯器自動產(chǎn)生的
ACC_ENUM 0x4000 字段是否 enum
  • 簡單名稱索引(name_index):指向常量池中一個 CONSTANT_Utf8_info 類型常量萝嘁,代表字段的簡單名稱。
  • 描述符索引(descriptor_index):指向常量池中一個 CONSTANT_Utf8_info 類型常量扬卷,代表字段和方法的描述符牙言。描述符的作用是用來描述字段的數(shù)據(jù)類型、方法的參數(shù)列表(包括數(shù)量怪得、類型以及順序)和返回值豪墅。
  • 屬性表集合(attributes):用于存儲一些額外的信息。

7隙轻、方法表集合

方法表的結(jié)構(gòu)與字段表一樣,依次包括了訪問標(biāo)志(access_flags)拔恰、名稱索引(name_index)、描述符索引(descriptor_index)基括、屬性表集合(attributes)幾項颜懊,這些數(shù)據(jù)項目的含義也非常類似,僅在訪問標(biāo)志和屬性表集合的可選項中有所區(qū)別风皿。

方法表結(jié)構(gòu):

類型 名稱 數(shù)量
u2 access_flags(字段訪問標(biāo)志) 1
u2 name_index(簡單名稱索引) 1
u2 descriptor_index(描述符索引) 1
u2 attributes_count(屬性表計數(shù)器) 1
attribute_info attributes(屬性表集合) attributes_count
  • 方法訪問標(biāo)志(access_flags):
標(biāo)志名稱 標(biāo)志值 含義
ACC_PUBLIC 0x0001 方法是否 public
ACC_PRIVATE 0x0002 方法是否 private
ACC_PROTECTED 0x0004 方法是否 protected
ACC_STATIC 0x0008 方法是否 static
ACC_FINAL 0x0010 方法是否 final
ACC_SYNCHRONIZED 0x0020 方法是否 synchronized
ACC_BRIDGE 0x0040 方法是否是由編譯器產(chǎn)生的橋接方法
ACC_VARARGS 0x0080 方法是否接受不定參數(shù)
ACC_NATIVE 0x0100 方法是否 native
ACC_ABSTRACT 0x0400 方法是否 abstract
ACC_STRICTFP 0x0800 方法是否 stricftp
ACC_SYNTHETIC 0x1000 方法是否由編譯器自動產(chǎn)生的

方法里的 Java 代碼河爹,經(jīng)過編譯器編譯成字節(jié)碼指令后,存放在方法屬性表集合中一個名為“Code”的屬性里面桐款。

8咸这、屬性表集合

在 Class 文件、字段表魔眨、方法表都可以攜帶自己的屬性表集合媳维,以用于描述某些場景專有的信息。

屬性表不要求各個屬性表具有嚴(yán)格的順序遏暴,并且只要不與已有屬性名重復(fù)侄刽,任何人實現(xiàn)的編譯器都可以向?qū)傩员碇袑懭胱约憾x的屬性信息,Java 虛擬機運行時會忽略掉它不認(rèn)識的屬性朋凉。

屬性表結(jié)構(gòu):

類型 名稱 數(shù)量
u2 attribute_name_index 1
u4 attribute_length 1
u1 info attribute_length

(1)Code 屬性

Java 程序方法體中的代碼經(jīng)過 Javac 編譯器處理后州丹,最終變成字節(jié)碼指令存儲在 Code 屬性內(nèi)。

Code 屬性表的結(jié)構(gòu):

類型 名稱 數(shù)量
u2 attribute_name_index 1
u4 attribute_length 1
u2 max_stack 1
u2 max_locals 1
u4 code_length 1
u1 code code_length
u2 exception_table_length 1
exception_info exception_table exception_table_length
u2 attritutes_count 1
attribute_info attritutes attritutes_count
  • attribute_name_index:代表該屬性的屬性名稱杂彭,是一項指向 CONSTANT_Uft8_info 型常量的索引墓毒,常量值固定為“Code”。
  • attribute_length:代表屬性值的長度亲怠。
  • max_stack:代表操作數(shù)棧深度的最大值所计。
  • max_locals:代表局部變量表所需的存儲空間。
  • code_length:代表字節(jié)碼長度团秽。
  • code:用于存儲字節(jié)碼指令的一系列字節(jié)流醉箕。

(2)Exceptions 屬性

用于列舉出方法中可能拋出的受查異常,也就是方法描述時在 throws 關(guān)鍵字后列舉的異常徙垫。

Exceptions 屬性表的結(jié)構(gòu):

類型 名稱 數(shù)量
u2 attribute_name_index 1
u4 attribute_length 1
u2 number_of_exceptions 1
u2 exception_index_table number_of_exceptions

(3)...

三、字節(jié)碼指令簡介

Java 虛擬機的指令由一個操作碼和零至多個操作數(shù)構(gòu)成放棒。由于 Java 虛擬機采用面向操作數(shù)棧而不是寄存器的架構(gòu)姻报,所有大多數(shù)指令都不包括操作數(shù),只有一個操作碼间螟。但是大多數(shù)指令都包含了其操作所對應(yīng)的數(shù)據(jù)類型信息吴旋。

如果不考慮異常處理损肛,Java 虛擬機的解釋器可以使用下面的偽代碼當(dāng)作最基本的執(zhí)行模型來理解:

do {
    自動計算 PC 寄存器的值加 1;
    根據(jù) PC 寄存器的指示位置,從字節(jié)碼流中取出操作碼;
    if ( 字節(jié)碼存在操作數(shù) ) 從字節(jié)碼流中取出操作數(shù);
    執(zhí)行操作碼所定義的操作;
}

對于大多數(shù)與數(shù)據(jù)類型相關(guān)的字節(jié)碼指令荣瑟,它們的操作碼助記符中都有特殊的字符來表示專門為哪種數(shù)據(jù)類型服務(wù):i 代表對 int 類型的數(shù)據(jù)操作治拿,l 代表 long,s 代表 short笆焰,b 代表 byte劫谅,c 代表 char,f 代表 float嚷掠,d 代表 double捏检,a 代表 reference。

1不皆、加載和存儲指令

加載和存儲指令用于將數(shù)據(jù)在棧幀中的局部變量表和操作數(shù)棧之間來回傳輸贯城,這類指令包括:

  • 將一個局部變量加載到操作棧:iload、iload_<n>霹娄、lload能犯、lload_<n>、fload犬耻、fload_<n>踩晶、dload、dload_<n>香追、aload合瓢、aload_<n>。
  • 將一個數(shù)值從操作數(shù)棧存儲到局部變量表:istore透典、istore_<n>晴楔、lstore、lstore_<n>峭咒、fstore税弃、fstore_<n>、dstore凑队、dstore_<n>则果、astore、astore_<n>漩氨。
  • 將一個常量加載到操作數(shù)棧:bipush西壮、sipush、ldc叫惊、ldc_w款青、ldc2_w、aconst_null霍狰、iconst_m1抡草、iconst_<i>饰及、lconst_<l>、fconst_<f>康震、dconst_<d>燎含。
  • 擴充局部變量表的訪問索引的指令:wide。

以上列舉的指令助記符中腿短,有一部分是以尖括號結(jié)尾的指令屏箍。這幾組指令是帶有一個操作數(shù)的通用指令(如 iload)的特殊形式,它們省略了顯式的操作數(shù)答姥,而是將操作數(shù)隱含在指令中铣除。例如:iload_0 代表操作數(shù)為 0 的 iload 指令。

2鹦付、運算指令

運算或算術(shù)指令用于對兩個操作數(shù)以上的值進行某種特定運算尚粘,并把結(jié)果重新存入到操作數(shù)棧頂。大體上算術(shù)指令可分為兩種:對整型數(shù)據(jù)進行運算的指令和對浮點型數(shù)據(jù)進行運算的指令敲长。所有的算術(shù)指令如下:

  • 加法指令:iadd郎嫁、ladd、fadd祈噪、dadd泽铛。
  • 減法指令:isub、lsub辑鲤、fsub盔腔、dsub。
  • 乘法指令:imul月褥、lmul弛随、fmul、dmul宁赤。
  • 除法指令:idiv舀透、ldiv、fdiv决左、ddiv愕够。
  • 求余指令:irem、lrem佛猛、frem惑芭、drem。
  • 取反指令:ineg继找、lneg强衡、fneg、dneg。
  • 位移指令:ishl漩勤、ishr、iushr缩搅、lshl越败、lshr、lushr硼瓣。
  • 按位或指令:ior究飞、lor。
  • 按位與指令:iand堂鲤、land亿傅。
  • 按位異或指令:ixor、lxor瘟栖。
  • 局部變量自增指令:iinc葵擎。
  • 比較指令:dcmpg、dcmpl半哟、fcmpg酬滤、fcmpl、lcmp寓涨。

3盯串、類型轉(zhuǎn)換指令

類型轉(zhuǎn)換指令可以將兩種不同的數(shù)值類型進行相互轉(zhuǎn)換,這些轉(zhuǎn)換操作一般用于實現(xiàn)用戶代碼中的顯式類型轉(zhuǎn)換操作戒良,或者用來處理字節(jié)碼指令集中數(shù)據(jù)類型相關(guān)指令無法與數(shù)據(jù)類型一一對應(yīng)的問題体捏。

Java 虛擬機直接支持(即轉(zhuǎn)換時無需顯示的轉(zhuǎn)換指令)以下數(shù)值類型的寬化類型轉(zhuǎn)換(小范圍類型向大范圍類型的安全轉(zhuǎn)換):

  • int 到 long、float糯崎、double几缭。
  • long 到 float、double拇颅。
  • float 到 double奏司。

相對的,處理窄化類型轉(zhuǎn)換時樟插,必須顯示地使用轉(zhuǎn)換指令來完成韵洋,這些指令包括:i2b、i2c黄锤、i2s搪缨、l2i、f2i鸵熟、f2l副编、d2i、d2l流强、d2f痹届。窄化類型轉(zhuǎn)換可能會導(dǎo)致轉(zhuǎn)換結(jié)果產(chǎn)生不同的正負(fù)號呻待、不同的數(shù)量級的情況,轉(zhuǎn)換過程很可能會導(dǎo)致數(shù)值的精度丟失队腐。

4蚕捉、對象創(chuàng)建與訪問指令

雖然類實例和數(shù)組都是對象,但 Java 虛擬機對類實例和數(shù)組的創(chuàng)建與操作使用了不同的字節(jié)碼指令柴淘。相關(guān)指令如下:

  • 創(chuàng)建類實例的指令:new迫淹。
  • 創(chuàng)建數(shù)組的指令:newarray、anewarray为严、multianewarray敛熬。
  • 訪問類字段和實例字段的指令:getstatic、putstatic第股、getfield应民、putfield。
  • 把一個數(shù)組元素加載到操作數(shù)棧的指令:baload炸茧、caload瑞妇、saload、iaload梭冠、laload辕狰、faload、daload控漠、aaload蔓倍。
  • 將一個操作數(shù)棧的值存儲到數(shù)組元素中的指令:bastore、castore盐捷、sastore偶翅、iastore、fastore碉渡、dastore聚谁、aastore。
  • 取數(shù)組長度的指令:arraylength滞诺。
  • 檢查類實例類型的指令:instanceof形导、checkcast。

5习霹、操作數(shù)棧管理指令

Java 虛擬機提供了一些用于直接操作操作數(shù)棧的指令朵耕,包括:

  • 將操作數(shù)棧的棧頂一個或兩個元素出棧:pop、pop2淋叶。
  • 復(fù)制棧頂一個或兩個數(shù)值并將復(fù)制值重新壓入棧頂:dup阎曹、dup2、dup_x1、dup2_x1处嫌、dup_x2栅贴、dup2_x2。
  • 將棧最頂端的兩個數(shù)值互換:swap锰霜。

6筹误、控制轉(zhuǎn)移指令

控制轉(zhuǎn)移指令可以讓 Java 虛擬機有條件或無條件地從指定位置的指令繼續(xù)執(zhí)行程序,而不是從控制轉(zhuǎn)移指令的下一條指令繼續(xù)執(zhí)行程序癣缅。從概念模型上理解,可認(rèn)為控制轉(zhuǎn)移指令就是在有條件或無條件地修改 PC 寄存器的值哄酝∮汛妫控制轉(zhuǎn)移指令如下:

  • 條件分支:ifeq、iflt陶衅、ifle屡立、ifne、ifgt搀军、ifge膨俐、ifnull、ifnonnull罩句、if_icmpeq焚刺、if_icmpne、if_icmplt门烂、if_icmpgt乳愉、if_icmple、if_icmpge屯远、if_acmpeq蔓姚、if_acmpne。
  • 復(fù)合條件分支:tableswitch慨丐、lookupswitch坡脐。
  • 無條件分支:goto、goto_w房揭、jsr备闲、jsr_w、ret崩溪。

7浅役、方法調(diào)用和返回指令

方法調(diào)用指令與數(shù)據(jù)類型無關(guān),包括:

  • invokevirtual 指令:用于調(diào)用對象的實例方法伶唯,根據(jù)對象的實際類型進行分派(虛方法分派)觉既,這是 Java 中最常見的方法分派方式。
  • invokeinterface 指令:用于調(diào)用接口方法,它會在運行時搜索一個實現(xiàn)了這個接口方法的對象瞪讼,找出合適的方法進行調(diào)用钧椰。
  • invokespecial 指令:用于調(diào)用一些需要特殊處理的實例方法,包括實例初始化方法符欠、私有方法和父類方法嫡霞。
  • invokestatic 指令:用于調(diào)用類方法。
  • invokedynamic 指令:用于在運行時動態(tài)解析出調(diào)用點限定符所引用的方法希柿,并執(zhí)行該方法诊沪。前 4 條調(diào)用指令的分派邏輯固化在 Java 虛擬機內(nèi)部,而 invokedynamic 指令的分派邏輯是由用戶所設(shè)定的引導(dǎo)方法決定的曾撤。

方法返回指令是根據(jù)返回值的類型區(qū)分的端姚,包括:ireturn(用于返回值是 boolean、byte挤悉、char渐裸、short、int 的方法)装悲、lreturn昏鹃、freturn、dreturn诀诊、areturn洞渤、return(用于 void 方法、實例初始化方法畏梆、類和接口的類初始化方法)您宪。

8、異常處理指令

Java 虛擬機中顯式拋出異常的操作(throw 語句)都由 athrow 指令實現(xiàn)奠涌。而處理異常(catch 語句)則不是由字節(jié)碼指令來實現(xiàn)的(很久之前曾經(jīng)使用 jsr 和 ret 指令實現(xiàn))宪巨,而是采用異常表來完成。

9溜畅、同步指令

Java 虛擬機可以支持方法級的同步和方法內(nèi)部一段指令序列的同步捏卓,這兩種同步結(jié)構(gòu)都是使用管程(Monitor)來支持的。

方法級的同步是隱式的慈格,即無須通過字節(jié)碼指令來控制怠晴。虛擬機可以從方法訪問標(biāo)志 ACC_SYNCHRONIZED 得知一個方法是否聲明為同步方法。如果方法訪問標(biāo)志 ACC_SYNCHRONIZED 被設(shè)置為 true浴捆,執(zhí)行線程就要求先成功持有管程蒜田,然后才能執(zhí)行方法,最后當(dāng)方法完成時釋放管程选泻。

同步一段指令集序列通常是由 synchronized 語句來表示的冲粤,Java 虛擬機的指令集中由 monitorenter 和 monitorexit 兩條指令來支持 synchronized 關(guān)鍵字語義美莫。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市梯捕,隨后出現(xiàn)的幾起案子厢呵,更是在濱河造成了極大的恐慌,老刑警劉巖傀顾,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件襟铭,死亡現(xiàn)場離奇詭異,居然都是意外死亡短曾,警方通過查閱死者的電腦和手機寒砖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嫉拐,“玉大人入撒,你說我怎么就攤上這事⊥盅遥” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵璃赡,是天一觀的道長判哥。 經(jīng)常有香客問我,道長碉考,這世上最難降的妖魔是什么塌计? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮侯谁,結(jié)果婚禮上锌仅,老公的妹妹穿的比我還像新娘。我一直安慰自己墙贱,他們只是感情好热芹,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著惨撇,像睡著了一般伊脓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上魁衙,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天报腔,我揣著相機與錄音,去河邊找鬼剖淀。 笑死纯蛾,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的纵隔。 我是一名探鬼主播翻诉,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼炮姨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了米丘?” 一聲冷哼從身側(cè)響起剑令,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拄查,沒想到半個月后吁津,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡堕扶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年碍脏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稍算。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡典尾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出糊探,到底是詐尸還是另有隱情逝她,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布响委,位于F島的核電站崭别,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏瞪慧。R本人自食惡果不足惜髓考,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望弃酌。 院中可真熱鬧,春花似錦妓湘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽竣灌。三九已至,卻和暖如春初嘹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背屯烦。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工房铭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留温眉,地道東北人缸匪。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像类溢,于是被迫代替她去往敵國和親凌蔬。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

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