java class文件結(jié)構(gòu)

(<深入分析Java Web技術(shù)內(nèi)幕>筆記)
java語言在宣傳時(shí)打出的名號就是"一次編譯,到處運(yùn)行", 也就是支持跨平臺運(yùn)行,其實(shí)這是java文件編譯成class文件來實(shí)現(xiàn)的,那么class文件是怎么生成的?clss文件又有哪些內(nèi)容?本篇筆記就是記錄相關(guān)的學(xué)習(xí)內(nèi)容的.

JVM指令集

先來一段幾乎每個(gè)人入門一門語言都會寫的代碼:

public class ClassLearn {
    public static void main(String[] args) {
        System.out.println("hello world!");
    }
}

就是一個(gè)類有一個(gè)main方法,方法內(nèi)部打印了"hello world!",我們先將其編譯為class文件,再運(yùn)行:

// oolong是一種匯編語言,可以編譯class文件為.j
java  COM.sootNsmoke.oolong.Gnoloo ClassLearn.class

會生成一個(gè)ClassLearn.j文件,查看一下文件內(nèi)容:


以"."符號開頭表示是一個(gè)基本的屬性項(xiàng),就是一個(gè)java的基本概念(一個(gè)類,方法,屬性,對象或者一個(gè)接口)

與類相關(guān)的指令

  • .source ClassLearn.java表示代碼的源文件是ClassLearn.java
  • .class public super ClassLearn表示這是一個(gè)類且公有的類名是ClassLearn
  • .super java/lang/Object表示這個(gè)類的父類是Object

與類相關(guān)的指令:

指令 參數(shù) 解釋
checkcast class 檢驗(yàn)類型轉(zhuǎn)換(ClassCastException)
getfield class/field desc 獲取類的實(shí)例域,并將值壓入棧頂
getstatic class/field desc 獲取類的靜態(tài)域,并將值壓入棧頂
instanceof class 檢查對象是否是類的實(shí)例,是1壓入棧頂,否0壓入棧頂
new class 創(chuàng)建一個(gè)對象,將其引入值壓入棧頂

方法定義

  • .method public <init> ()V 表示是一個(gè)公有方法,沒有參數(shù),返回值是void,<init>表示是構(gòu)造方法
  • .method public static main([Ljava/lang/String;)V與上一條類似,[表示數(shù)組,L表示是一個(gè)類形式而不是基本數(shù)據(jù)類型(int,char等),凡是L最后都以;結(jié)尾,表示類結(jié)束

與方法相關(guān)的JVM指令:

指令 操作數(shù) 解釋
invokeinterface class/method desc n 調(diào)用接口方法
invokespecial class/method desc 調(diào)用超類構(gòu)造方法,實(shí)例初始化方法,私有方法
invokestatic class/method desc 調(diào)用靜態(tài)方法
invokevirtual class/method desc 調(diào)用實(shí)例方法

類的屬性的定義

數(shù)據(jù)類型:

數(shù)據(jù)類型 表示方式
數(shù)組 [
L;
byte B
boolean Z
char C
double D
float F
int I
long J
short S
void V

修飾屬性:

修飾符 說明
public 公有
private 私有
protected 子類和包可見
static 靜態(tài)
final 不可修改
volatile 弱引用
transient 臨時(shí)屬性

class文件頭的表示形式

看一看之前的代碼字節(jié)碼形式是怎么樣的:

java COM.sootNsmoke.oolong.DumpClass ClassLearn.class

輸出:

000000 cafebabe          magic = ca fe ba be
000004 0000              minor version = 0
000006 0034              major version = 52
000008 001d              29 constants
00000a 0a0006000f           1. Methodref class #6 name-and-type #15
00000f 0900100011           2. Fieldref class #16 name-and-type #17
000014 080012               3. String #18
000017 0a00130014           4. Methodref class #19 name-and-type #20
00001c 070015               5. Class name #21
00001f 070016               6. Class name #22
000022 010006               7. UTF length=6
000025 3c696e69743e                       <init>
00002b 010003               8. UTF length=3
00002e 282956                             ()V
000031 010004               9. UTF length=4
000034 436f6465                           Code
000038 01000f               10. UTF length=15
00003b 4c696e654e756d6265725461626c65     LineNumberTable
00004a 010004               11. UTF length=4
00004d 6d61696e                           main
000051 010016               12. UTF length=22
000054 285b4c6a6176612f6c616e672f537472   ([Ljava/lang/Str
000064 696e673b2956                       ing;)V
00006a 01000a               13. UTF length=10
00006d 536f7572636546696c65               SourceFile
000077 01000f               14. UTF length=15
00007a 436c6173734c6561726e2e6a617661     ClassLearn.java
000089 0c00070008           15. NameAndType name #7 descriptor #8
00008e 070017               16. Class name #23
000091 0c00180019           17. NameAndType name #24 descriptor #25
000096 01000c               18. UTF length=12
000099 68656c6c6f20776f726c6421           hello world!
0000a5 07001a               19. Class name #26
0000a8 0c001b001c           20. NameAndType name #27 descriptor #28
0000ad 01000a               21. UTF length=10
0000b0 436c6173734c6561726e               ClassLearn
0000ba 010010               22. UTF length=16
0000bd 6a6176612f6c616e672f4f626a656374   java/lang/Object
0000cd 010010               23. UTF length=16
0000d0 6a6176612f6c616e672f53797374656d   java/lang/System
0000e0 010003               24. UTF length=3
0000e3 6f7574                             out
0000e6 010015               25. UTF length=21
0000e9 4c6a6176612f696f2f5072696e745374   Ljava/io/PrintSt
0000f9 7265616d3b                         ream;
0000fe 010013               26. UTF length=19
000101 6a6176612f696f2f5072696e74537472   java/io/PrintStr
000111 65616d                             eam
000114 010007               27. UTF length=7
000117 7072696e746c6e                     println
00011e 010015               28. UTF length=21
000121 284c6a6176612f6c616e672f53747269   (Ljava/lang/Stri
000131 6e673b2956                         ng;)V
000136 0021              access_flags = 33
000138 0005              this = #5
00013a 0006              super = #6
00013c 0000              0 interfaces
00013e 0000              0 fields
000140 0002              2 methods
                         Method 0:
000142 0001                 access flags = 1
000144 0007                 name = #7<<init>>
000146 0008                 descriptor = #8<()V>
000148 0001                 1 field/method attributes:
                            field/method attribute 0
00014a 0009                    name = #9<Code>
00014c 0000001d                length = 29
000150 0001                    max stack: 1
000152 0001                    max locals: 1
000154 00000005                code length: 5
000158 2a                      0 aload_0
000159 b70001                  1 invokespecial #1
00015c b1                      4 return
00015d 0000                    0 exception table entries:
00015f 0001                    1 code attributes:
                               code attribute 0:
000161 000a                       name = #10<LineNumberTable>
000163 00000006                   length = 6
                                  Line number table:
000167 0001                       length = 1
000169 00000008                      start pc: 0 line number: 8
                         Method 1:
00016d 0009                 access flags = 9
00016f 000b                 name = #11<main>
000171 000c                 descriptor = #12<([Ljava/lang/String;)V>
000173 0001                 1 field/method attributes:
                            field/method attribute 0
000175 0009                    name = #9<Code>
000177 00000025                length = 37
00017b 0002                    max stack: 2
00017d 0001                    max locals: 1
00017f 00000009                code length: 9
000183 b20002                  0 getstatic #2
000186 1203                    3 ldc #3
000188 b60004                  5 invokevirtual #4
00018b b1                      8 return
00018c 0000                    0 exception table entries:
00018e 0001                    1 code attributes:
                               code attribute 0:
000190 000a                       name = #10<LineNumberTable>
000192 0000000a                   length = 10
                                  Line number table:
000196 0002                       length = 2
000198 0000000a                      start pc: 0 line number: 10
00019c 0008000b                      start pc: 8 line number: 11
0001a0 0001              1 classfile attributes
                         Attribute 0:
0001a2 000d                 name = #13<SourceFile>
0001a4 00000002             length = 2
0001a8 000e                 sourcefile index = #14
Done.

看起來特別長,但是真正需要理解的并不是很多,先看頭部信息:

000000 cafebabe          magic = ca fe ba be
000004 0000              minor version = 0
000006 0034              major version = 52

第一行是一個(gè)標(biāo)識符,表示是一個(gè)標(biāo)準(zhǔn)的class文件,由一個(gè)32位無符號整數(shù)表示,cafebabe是其16進(jìn)制表示形式,如果不是這個(gè),JVM就不認(rèn)為這是一個(gè)class文件,也就不會加載,后面兩個(gè)字節(jié)表示說最大版本和最小版本的范圍,從最初的Java到Java8是45.3~53.0,JVM在加載時(shí)也會檢查這個(gè)是否符合條件

常量池

根據(jù)輸出顯示,共有29個(gè)常量,但是看顯示只有1~28,是因?yàn)?是保留常量,每個(gè)常量都由3個(gè)字節(jié)描述:



第一個(gè)表示這個(gè)常量是什么類型的,JVM中定義了12種類型常量,每個(gè)都會對應(yīng)一個(gè)數(shù)值




接下來分別說明幾個(gè)較重要的

UTF8常量

字符編碼格式,存儲多個(gè)字節(jié)長度的字符串值(類名,方法名等)


Fieldref,Methodref常量

描述Class中的屬性項(xiàng)和方法的



第一個(gè)字節(jié)09代表是Fieldref類型,10則代表Methodref類型;后面兩個(gè)字節(jié)代表屬于哪個(gè)類;最后兩個(gè)字表示常量的name和type

Class常量

表示該類的名稱,會指向另一個(gè)UTF8類型的常量(之前提到了UTF8就是表示類名和方法名等的字符串)



利用之前的輸出

00008e 070017               16. Class name #23

第一個(gè)字節(jié)07就代表該常量是Class類型,后面兩個(gè)字節(jié)0017指向第23個(gè)常量,而第23個(gè)常量是:

0000cd 010010               23. UTF length=16
0000d0 6a6176612f6c616e672f53797374656d   java/lang/System

就是一個(gè)UTF8常量,存儲的是java/lang/System,也就是類名

NameAndType常量

為了表示MethodrefFieldref的名稱和類型描述做進(jìn)一步說明存在的,名稱也是通常由UTF8常量描述,類型也由UTF8描述


0007指向第7個(gè)常量,表示MethodrefFieldref的名稱,而0008則表示Methodref的返回類型或Fieldref參數(shù)類型

類信息

常量列表后面就是類本身的信息描述了,如訪問控制,名稱,類型,是否有父類,是否實(shí)現(xiàn)了接口等

000136 0021              access_flags = 33
000138 0005              this = #5
00013a 0006              super = #6
00013c 0000              0 interfaces


兩個(gè)字節(jié)只使用了5bit,ACC_PUBLIC代表類是否是public類(是為1,否為0),ACC_FINAL代表是否是final類,ACC_SUPER代表是否存在父類(除了Obejct其他類都有父類),ACC_INTERFACE代表是否是接口類,ACC_ABSTRACT代表是否是抽象類;后面兩個(gè)字節(jié)0005代表該類名稱,指向第5個(gè)常量;后面的0006代表父類的名稱,指向第6個(gè)常量;0000代表沒有實(shí)現(xiàn)接口類

Fields和Methods定義

00013e 0000              0 fields
000140 0002              2 methods
                         Method 0:
000142 0001                 access flags = 1
000144 0007                 name = #7<<init>>
000146 0008                 descriptor = #8<()V>
000148 0001                 1 field/method attributes:
                            field/method attribute 0
00014a 0009                    name = #9<Code>
00014c 0000001d                length = 29
000150 0001                    max stack: 1
000152 0001                    max locals: 1
000154 00000005                code length: 5
000158 2a                      0 aload_0
000159 b70001                  1 invokespecial #1
00015c b1                      4 return
00015d 0000                    0 exception table entries:
00015f 0001                    1 code attributes:
                               code attribute 0:
000161 000a                       name = #10<LineNumberTable>
000163 00000006                   length = 6
                                  Line number table:
000167 0001                       length = 1
000169 00000008                      start pc: 0 line number: 8

Method1與Method0類似,就不粘過來了
前4個(gè)字節(jié)表示該類有幾個(gè)屬性,幾個(gè)方法,后面就是每個(gè)屬性和類的具體定義了
方法當(dāng)然也有訪問控制,也由兩個(gè)字節(jié)定義:



與類描述基本一致,就不列舉說明了

接下來4個(gè)字節(jié):

000144 0007                 name = #7<<init>>
000146 0008                 descriptor = #8<()V>

定義了方法的名稱和類型描述(NameAndType)

接下來是具體的代碼實(shí)現(xiàn)的定義了,包括代碼長度(最長64K字節(jié)長度)

接下來:

000150 0001                    max stack: 1
000152 0001                    max locals: 1

定義了該方法使用的棧的深度及本地常量的最大個(gè)數(shù),會在JVM類加載做檢查,超過這兩個(gè)值,會拒絕加載

接下來:

000154 00000005                code length: 5
000158 2a                      0 aload_0
000159 b70001                  1 invokespecial #1
00015c b1                      4 return

表示這個(gè)方法的代碼對應(yīng)的JVM指令,00000005代表命令有5個(gè)字節(jié)

接下來:

00015d 0000                    0 exception table entries:

定義了使用的異常,0000代表沒有定義拋出的異常

接下來是方法存在的一些代碼屬性的描述,描述的是代碼本身的一些額外信息

00015f 0001                    1 code attributes:
                               code attribute 0:
000161 000a                       name = #10<LineNumberTable>
000163 00000006                   length = 6
                                  Line number table:
000167 0001                       length = 1
000169 00000008                      start pc: 0 line number: 8

0001代表只有一行對應(yīng)關(guān)系,指向0000和0008,0000指向運(yùn)行時(shí)的行指針,0008指向?qū)嶋H源代碼的行數(shù),每個(gè)都是兩個(gè)字節(jié),所以可知Java代碼最大行數(shù)到65535,超過class就沒辦法表示出來了

Javap生成class文件

之前所有介紹的內(nèi)容都是靠oolong生成的class文件的二進(jìn)制表示,還可以通過JDK自帶的javap來生成class文件,而且更易理解:

javap -verbose ClassLearn >  ClassLearn.txt

查看輸出:


  1 Classfile /Users/lkc/Desktop/Code/Learn/out/production/TechCollect/ClassLearn.class
  2   Last modified 2017-8-7; size 672 bytes
  3   MD5 checksum 733971818278fd4709847bba1a9720bd
  4   Compiled from "ClassLearn.java"
  5 public class ClassLearn
  6   minor version: 0
  7   major version: 52
  8   flags: ACC_PUBLIC, ACC_SUPER
  9 Constant pool:
 10    #1 = Methodref          #6.#26         // java/lang/Object."<init>":()V
 11    #2 = String             #27            // hello,world!
 12    #3 = Fieldref           #28.#29        // java/lang/System.out:Ljava/io/PrintStream;
 13    #4 = Methodref          #30.#31        // java/io/PrintStream.println:(Ljava/lang/String;)V
 14    #5 = Class              #32            // ClassLearn
 15    #6 = Class              #33            // java/lang/Object
 16    #7 = Utf8               <init>
 17    #8 = Utf8               ()V
 18    #9 = Utf8               Code
 19   #10 = Utf8               LineNumberTable
 20   #11 = Utf8               LocalVariableTable
 21   #12 = Utf8               this
 22   #13 = Utf8               LClassLearn;
 23   #14 = Utf8               main
 24   #15 = Utf8               ([Ljava/lang/String;)V
 25   #16 = Utf8               i
 26   #17 = Utf8               I
 27   #18 = Utf8               args
 28   #19 = Utf8               [Ljava/lang/String;
 29   #20 = Utf8               str
 30   #21 = Utf8               Ljava/lang/String;
 31   #22 = Utf8               StackMapTable
 32   #23 = Class              #34            // java/lang/String
 33   #24 = Utf8               SourceFile
 34   #25 = Utf8               ClassLearn.java
 35   #26 = NameAndType        #7:#8          // "<init>":()V
 36   #27 = Utf8               hello,world!
 37   #28 = Class              #35            // java/lang/System
 38   #29 = NameAndType        #36:#37        // out:Ljava/io/PrintStream;
 39   #30 = Class              #38            // java/io/PrintStream
 40   #31 = NameAndType        #39:#40        // println:(Ljava/lang/String;)V
 41   #32 = Utf8               ClassLearn
 42   #33 = Utf8               java/lang/Object
  43   #34 = Utf8               java/lang/String
 44   #35 = Utf8               java/lang/System
 45   #36 = Utf8               out
 46   #37 = Utf8               Ljava/io/PrintStream;
 47   #38 = Utf8               java/io/PrintStream
 48   #39 = Utf8               println
 49   #40 = Utf8               (Ljava/lang/String;)V
 50 {
 51   public ClassLearn();
 52     descriptor: ()V
 53     flags: ACC_PUBLIC
 54     Code:
 55       stack=1, locals=1, args_size=1
 56          0: aload_0
 57          1: invokespecial #1                  // Method java/lang/Object."<init>":()V
 58          4: return
 59       LineNumberTable:
 60         line 8: 0
 61       LocalVariableTable:
 62         Start  Length  Slot  Name   Signature
 63             0       5     0  this   LClassLearn;
 64
 65   public static void main(java.lang.String[]);
 66     descriptor: ([Ljava/lang/String;)V
 67     flags: ACC_PUBLIC, ACC_STATIC
 68     Code:
 69       stack=2, locals=3, args_size=1
 70          0: ldc           #2                  // String hello,world!
 71          2: astore_1
 72          3: iconst_0
 73          4: istore_2
 74          5: iload_2
 75          6: iconst_3
 76          7: if_icmpge     23
 77         10: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
 78         13: aload_1
 79         14: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
 80         17: iinc          2, 1
 81         20: goto          5
 82         23: return
 83       LineNumberTable:
 84         line 10: 0
  85         line 11: 3
 86         line 12: 10
 87         line 11: 17
 88         line 14: 23
 89       LocalVariableTable:
 90         Start  Length  Slot  Name   Signature
 91             5      18     2     i   I
 92             0      24     0  args   [Ljava/lang/String;
 93             3      21     1   str   Ljava/lang/String;
 94       StackMapTable: number_of_entries = 2
 95         frame_type = 253 /* append */
 96           offset_delta = 5
 97           locals = [ class java/lang/String, int ]
 98         frame_type = 250 /* chop */
 99           offset_delta = 17
100 }
101 SourceFile: "ClassLearn.java"

三個(gè)地方LineNumberTable,LocalVariableTable,StackMapTable

LineNumberTable

LineNumberTable下面有多個(gè)line a:b,每個(gè)line表示一行,a表示在類文件的第幾行,b表示在JVM指令中的pc偏移量



拿line 14:23舉例,14就對應(yīng)return這一句,23代表偏移地址,也就是指:

82         23: return

可以發(fā)現(xiàn)是一致的

LocalVariableTable

 89       LocalVariableTable:
 90         Start  Length  Slot  Name   Signature
 91             5      18     2     i   I
 92             0      24     0  args   [Ljava/lang/String;
 93             3      21     1   str   Ljava/lang/String;

可以很容易看出,LocalVariableTable由五部分組成,Start和Length表示變量有效作用域的偏移地址;Start表示變量被賦值到某個(gè)Slot中的指令的下一條指令的偏移地址;Length表示變量作用域總共占用的指令數(shù)對應(yīng)的偏移量,所以作用域就是[Start,Start+Length];Slot表示該變量占用的Slot編號;Name表示該變量的名稱;Signature表示該變量的類型
拿出一個(gè)來舉例:

 90         Start  Length  Slot  Name   Signature
 91             5      18     2     i   I

這里就表示變量"i"的類型是int,作用域是[5,23],也就是這一段:

 74          5: iload_2
 75          6: iconst_3
 76          7: if_icmpge     23
 77         10: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
 78         13: aload_1
 79         14: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
 80         17: iinc          2, 1
 81         20: goto          5
 82         23: return

與實(shí)際代碼比較,也就是整個(gè)for循環(huán)體直到方法結(jié)束,所以符合我們預(yù)期;還需要提一句的是其實(shí)Slot是可以出現(xiàn)重復(fù)的,只要實(shí)際代碼中作用域不重合Slot的編號是可以復(fù)用的.

StackMapTable

這里在我閱讀本書時(shí)發(fā)現(xiàn)沒有StackMapTable,因此特地查了下資料
這里是由Java6引入的一個(gè)叫做棧圖的概念,Java7中開始強(qiáng)制使用,實(shí)例說明:

 94       StackMapTable: number_of_entries = 2
 95         frame_type = 253 /* append */
 96           offset_delta = 5
 97           locals = [ class java/lang/String, int ]
 98         frame_type = 250 /* chop */
 99           offset_delta = 17

number_of_entries代表frame的個(gè)數(shù),這里也就是2個(gè),分別是frame_type = 253 /* append */frame_type = 250 /* chop */, 這里注釋的append就代表?xiàng)V芯植孔兞炕蝾愒黾?個(gè),chop相反代表減少一個(gè),還有一個(gè)same代表沒有變化;offset_delta代表每個(gè)frame的增量偏移量,第一個(gè)的偏移量就是offset_delta本身,其他幀的偏移量計(jì)算方法是前一幀的偏移量加上此幀的offset_delta+1;目前僅了解這么多,想詳細(xì)了解StackMapTable相關(guān)或者其他的class文件信息可以參照< Java虛擬機(jī)規(guī)范 se7 >

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末贫橙,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌岸蜗,老刑警劉巖鼻百,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件空幻,死亡現(xiàn)場離奇詭異默责,居然都是意外死亡但壮,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門凛驮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來裆站,“玉大人,你說我怎么就攤上這事黔夭『昕瑁” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵本姥,是天一觀的道長肩袍。 經(jīng)常有香客問我,道長婚惫,這世上最難降的妖魔是什么氛赐? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮先舷,結(jié)果婚禮上鹰祸,老公的妹妹穿的比我還像新娘。我一直安慰自己密浑,他們只是感情好蛙婴,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著尔破,像睡著了一般街图。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上懒构,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天餐济,我揣著相機(jī)與錄音,去河邊找鬼胆剧。 笑死絮姆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的秩霍。 我是一名探鬼主播篙悯,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼铃绒!你這毒婦竟也來了鸽照?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤颠悬,失蹤者是張志新(化名)和其女友劉穎矮燎,沒想到半個(gè)月后定血,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡诞外,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年澜沟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片峡谊。...
    茶點(diǎn)故事閱讀 38,566評論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡茫虽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出靖苇,到底是詐尸還是另有隱情席噩,我是刑警寧澤班缰,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布贤壁,位于F島的核電站,受9級特大地震影響埠忘,放射性物質(zhì)發(fā)生泄漏脾拆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一莹妒、第九天 我趴在偏房一處隱蔽的房頂上張望名船。 院中可真熱鬧,春花似錦旨怠、人聲如沸渠驼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽迷扇。三九已至,卻和暖如春爽哎,著一層夾襖步出監(jiān)牢的瞬間蜓席,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工课锌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留厨内,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓渺贤,卻偏偏與公主長得像雏胃,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子志鞍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評論 2 348

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

  • Java代碼必須要被編譯成class文件后丑掺,虛擬機(jī)才能夠加載運(yùn)行,要搞清楚Java的類加載機(jī)制述雾,首先必須要理解Cl...
    云飛揚(yáng)1閱讀 9,246評論 2 61
  • 每個(gè)使用Java的開發(fā)者都知道Java字節(jié)碼是在JRE中運(yùn)行(JRE: Java 運(yùn)行時(shí)環(huán)境)街州。JVM則是JRE中...
    燕京博士閱讀 1,398評論 0 6
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法兼丰,類相關(guān)的語法,內(nèi)部類的語法唆缴,繼承相關(guān)的語法鳍征,異常的語法,線程的語...
    子非魚_t_閱讀 31,596評論 18 399
  • 一、JVM內(nèi)幕:Java虛擬機(jī)詳解(java se 7規(guī)范) 直接上圖趟紊,再逐步解釋氮双。 上圖顯示的組件分兩個(gè)章節(jié)解釋...
    屈小勇閱讀 1,841評論 6 22
  • 下午突然感覺不舒服這深秋是要感冒么躺在床上昏昏沉沉 迷糊之間白茫茫風(fēng)打在臉上感覺頭還有些熱昨天買了機(jī)票才感覺雪季真...
    哈哈同學(xué)閱讀 140評論 0 0