A. 《深入理解java虛擬機(第二版)》pdf下載在線閱讀全文,求百度網盤雲資源
《深入理解Java虛擬機(第二版)》網路網盤pdf最新全集下載:
鏈接: https://pan..com/s/1VM5oW6jdDg5bWQJ5RCdNqg
B. 深入理解java虛擬機第二版和第三版的區別
區別:
第三版是一款針對java學習打造的圖書,它從Java程序員的角度出發,系統地將Java程序運行過程中涉及的各種知識整合到了一起,而第二版不僅技術更新、內容更豐富,而且實戰性更強。
C. 《深入理解Java虛擬機JVM高級特性與最佳實踐》epub下載在線閱讀,求百度網盤雲資源
《深入理解Java虛擬機(第3版)》(周志明)電子書網盤下載免費在線閱讀
資源鏈接:
鏈接:https://pan..com/s/1ng0b0CPBKKxMBv-zUSHsng
書名:深入理解Java虛擬機(第3版)
作者:周志明
豆瓣評分:9.5
出版社:機械工業出版社
出版年份:2019-12
頁數:540
內容簡介:內容介紹
這是一部從工作原理和工程實踐兩個維度深入剖析JVM的著作,是計算機領域公認的經典,繁體版在台灣也頗受歡迎。
自2011年上市以來,前兩個版本累計印刷36次,銷量超過30萬冊,兩家主要網路書店的評論近90000條,內容上近乎零差評,是原創計算機圖書領域不可逾越的豐碑。
第3版在第2版的基礎上做了重大修訂,內容更豐富、實戰性更強:根據新版JDK對內容進行了全方位的修訂和升級,圍繞新技術和生產實踐新增逾10萬字,包含近50%的全新內容,並對第2版中含糊、瑕疵和錯誤內容進行了修正。
全書一共13章,分為五大部分:
第一部分(第1章)走近Java
系統介紹了Java的技術體系、發展歷程、虛擬機家族,以及動手編譯JDK,了解這部分內容能對學習JVM提供良好的指引。
第二部分(第2~5章)自動內存管理
詳細講解了Java的內存區域與內存溢出、垃圾收集器與內存分配策略、虛擬機性能監控與故障排除等與自動內存管理相關的內容,以及10餘個經典的性能優化案例和優化方法;
第三部分(第6~9章)虛擬機執行子系統
深入分析了虛擬機執行子系統,包括類文件結構、虛擬機類載入機制、虛擬機位元組碼執行引擎,以及多個類載入及其執行子系統的實戰案例;
第四部分(第10~11章)程序編譯與代碼優化
詳細講解了程序的前、後端編譯與優化,包括前端的易用性優化措施,如泛型、主動裝箱拆箱、條件編譯等的內容的深入分析;以及後端的性能優化措施,如虛擬機的熱點探測方法、HotSpot 的即時編譯器、提前編譯器,以及各種常見的編譯期優化技術;
第五部分(第12~13章)高效並發
主要講解了Java實現高並發的原理,包括Java的內存模型、線程與協程,以及線程安全和鎖優化。
全書以實戰為導向,通過大量與實際生產環境相結合的案例分析和展示了解決各種Java技術難題的方案和技巧。
作者簡介:資深Java技術、機器學習和企業級開發技術專家,現任遠光軟體研究院院長,人工智慧博士在讀,著有知名暢銷書《深入理解Java虛擬機:JVM高級特性與最佳實踐》。
開源技術的積極倡導者和推動者,對計算機科學和相關的多個領域都有深刻的見解,尤其是人工智慧、Java開發和敏捷開發等領域。曾受邀在InfoQ和IBM DeveloperWorks等網站撰寫技術專欄。
著作頗豐,著有《深入理解Java虛擬機》《深入理解OSGi》,翻譯了《Java虛擬機規范》等著作。其中《深入理解Java虛擬機》第1版出版於2011年,已經出至第2版,不僅銷量好,而且口碑更好,累計印刷超過30次,仍長銷不衰,是中文計算機圖書領域公認的、難得一見的佳作。
D. java思維導圖
Java虛擬機是Java語言的運行環境,它是Java別具吸引力的特性之一,屬於Java的中級內容。在學習過Java初級知識後,工程師就需要學習Java虛擬機。
周志明的《深入理解Java虛擬機》詳細的介紹了Java虛擬機,但是學習的過程中會發現書本很厚,知識點很多,我最開始是採用有道雲筆記去記筆記,但是發現知識點過於分散,朋友建議我繪制Java虛擬機的思維導圖,更有助於學習Java虛擬機。
E. 《深入理解Java虛擬機(第2版)JVM高級特性與最佳實踐》epub下載在線閱讀,求百度網盤雲資源
《深入理解Java虛擬機(第2版)》(周志明)電子書網盤下載免費在線閱讀
資源鏈接:
鏈接:https://pan..com/s/1ySj-W7sTWYttLuIDrc6Bxw
書名:深入理解Java虛擬機(第2版)
作者:周志明
豆瓣評分:9.0
出版社:機械工業出版社
出版年份:2013-9-1
頁數:433
內容簡介:
《深入理解Java虛擬機:JVM高級特性與最佳實踐(第2版)》內容簡介:第1版兩年內印刷近10次,4家網上書店的評論近4?000條,98%以上的評論全部為5星級的好評,是整個Java圖書領域公認的經典著作和超級暢銷書,繁體版在台灣也十分受歡迎。第2版在第1版的基礎上做了很大的改進:根據最新的JDK 1.7對全書內容進行了全面的升級和補充;增加了大量處理各種常見JVM問題的技巧和最佳實踐;增加了若干與生產環境相結合的實戰案例;對第1版中的錯誤和不足之處的修正;等等。第2版不僅技術更新、內容更豐富,而且實戰性更強。
《深入理解Java虛擬機:JVM高級特性與最佳實踐(第2版)》共分為五大部分,圍繞內存管理、執行子系統、程序編譯與優化、高效並發等核心主題對JVM進行了全面而深入的分析,深刻揭示了JVM的工作原理。
第一部分從宏觀的角度介紹了整個Java技術體系、Java和JVM的發展歷程、模塊化,以及JDK的編譯,這對理解書中後面內容有重要幫助。
第二部分講解了JVM的自動內存管理,包括虛擬機內存區域的劃分原理以及各種內存溢出異常產生的原因;常見的垃圾收集演算法以及垃圾收集器的特點和工作原理;常見虛擬機監控與故障處理工具的原理和使用方法。
第三部分分析了虛擬機的執行子系統,包括類文件結構、虛擬機類載入機制、虛擬機位元組碼執行引擎。
第四部分講解了程序的編譯與代碼的優化,闡述了泛型、自動裝箱拆箱、條件編譯等語法糖的原理;講解了虛擬機的熱點探測方法、HotSpot的即時編譯器、編譯觸發條件,以及如何從虛擬機外部觀察和分析JIT編譯的數據和結果;
第五部分探討了Java實現高效並發的原理,包括JVM內存模型的結構和操作;原子性、可見性和有序性在Java內存模型中的體現;先行發生原則的規則和使用;線程在Java語言中的實現原理;虛擬機實現高效並發所做的一系列鎖優化措施。
作者簡介:
周志明,資深Java技術專家,對JavaEE企業級應用開發、OSGi、Java虛擬機和工作流等都有深入的研究,並在大量的實踐中積累了豐富的經驗。尤其精通Java虛擬機,撰寫了大量與JVM相關的經典文章,被各大技術社區爭相轉載,是ITeye等技術社區公認的Java虛擬機方面的領袖人物之一。除本書外,還著有經典著作《深入理解OSGi:Equinox原理、應用與最佳實踐》,廣獲讀者好評。現任遠光軟體股份有限公司開發部總經理兼架構師,先後參與過國家電網、南方電網等多個國家級大型ERP項目的平台架構工作,對軟體系統架構也有深刻的認識和體會。
F. 《深入理解Java虛擬機》pdf下載在線閱讀全文,求百度網盤雲資源
《深入理解Java虛擬機》網路網盤pdf最新全集下載:
鏈接: https://pan..com/s/1mIyCm1Wssk4Iy9P8haqfUw
G. 深入理解Java中為什麼內部類可以訪問外部類的成員
內部類簡介
雖然Java是一門相對比較簡單的編程語言,但是對於初學者, 還是有很多東西感覺雲里霧里,
理解的不是很清晰。內部類就是一個經常讓初學者感到迷惑的特性。 即使現在我自認為Java學的不錯了,
但是依然不是很清楚。其中一個疑惑就是為什麼內部類對象可以訪問外部類對象中的成員(包括成員變數和成員方法)?
早就想對內部類這個特性一探究竟了,今天終於抽出時間把它研究了一下。
內部類就是定義在一個類內部的類。定義在類內部的類有兩種情況:一種是被static關鍵字修飾的, 叫做靜態內部類,
另一種是不被static關鍵字修飾的, 就是普通內部類。 在下文中所提到的內部類都是指這種不被static關鍵字修飾的普通內部類。
靜態內部類雖然也定義在外部類的裡面, 但是它只是在形式上(寫法上)和外部類有關系,
其實在邏輯上和外部類並沒有直接的關系。而一般的內部類,不僅在形式上和外部類有關系(寫在外部類的裡面), 在邏輯上也和外部類有聯系。
這種邏輯上的關系可以總結為以下兩點:
1 內部類對象的創建依賴於外部類對象;
2 內部類對象持有指向外部類對象的引用。
上邊的第二條可以解釋為什麼在內部類中可以訪問外部類的成員。就是因為內部類對象持有外部類對象的引用。但是我們不禁要問, 為什麼會持有這個引用? 接著向下看, 答案在後面。
通過反編譯位元組碼獲得答案
在源代碼層面, 我們無法看到原因,因為Java為了語法的簡介, 省略了很多該寫的東西, 也就是說很多東西本來應該在源代碼中寫出, 但是為了簡介起見, 不必在源碼中寫出,編譯器在編譯時會加上一些代碼。 現在我們就看看Java的編譯器為我們加上了什麼?
首先建一個工程TestInnerClass用於測試。 在該工程中為了簡單起見, 沒有創建包, 所以源代碼直接在默認包中。在該工程中, 只有下面一個簡單的文件。
?
1
2
3
4
5
6
7
8
9
public class Outer {
int outerField = 0;
class Inner{
void InnerMethod(){
int i = outerField;
}
}
}
該文件很簡單, 就不用過多介紹了。 在外部類Outer中定義了內部類Inner, 並且在Inner的方法中訪問了Outer的成員變數outerField。
雖然這兩個類寫在同一個文件中, 但是編譯完成後, 還是生成各自的class文件:
這里我們的目的是探究內部類的行為, 所以只反編譯內部類的class文件Outer$Inner.class 。 在命令行中, 切換到工程的bin目錄, 輸入以下命令反編譯這個類文件:
?
1
javap -classpath . -v Outer$Inner
-classpath . 說明在當前目錄下尋找要反編譯的class文件
-v 加上這個參數輸出的信息比較全面。包括常量池和方法內的局部變數表, 行號, 訪問標志等等。
注意, 如果有包名的話, 要寫class文件的全限定名, 如:
?
1
javap -classpath . -v com..Outer$Inner
反編譯的輸出結果很多, 為了篇幅考慮, 在這里我們省略了常量池。 下面給出除了常量池之外的輸出信息。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
{
final Outer this$0;
flags: ACC_FINAL, ACC_SYNTHETIC
Outer$Inner(Outer);
flags:
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: putfield #10 // Field this$0:LOuter;
5: aload_0
6: invokespecial #12 // Method java/lang/Object."<init>":()V
9: return
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 this LOuter$Inner;
void InnerMethod();
flags:
Code:
stack=1, locals=2, args_size=1
0: aload_0
1: getfield #10 // Field this$0:LOuter;
4: getfield #20 // Field Outer.outerField:I
7: istore_1
8: return
LineNumberTable:
line 7: 0
line 8: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this LOuter$Inner;
8 1 1 i I
}</init>
首先我們會看到, 第一行的信息如下:
?
1
final Outer this$0;
這句話的意思是, 在內部類Outer$Inner中, 存在一個名字為this$0 , 類型為Outer的成員變數, 並且這個變數是final的。
其實這個就是所謂的「在內部類對象中存在的指向外部類對象的引用」。但是我們在定義這個內部類的時候, 並沒有聲明它,
所以這個成員變數是編譯器加上的。
雖然編譯器在創建內部類時為它加上了一個指向外部類的引用, 但是這個引用是怎樣賦值的呢?畢竟必須先給他賦值,它才能指向外部類對象。下面我們把注意力轉移到構造函數上。 下面這段輸出是關於構造函數的信息。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Outer$Inner(Outer);
flags:
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: putfield #10 // Field this$0:LOuter;
5: aload_0
6: invokespecial #12 // Method java/lang/Object."<init>":()V
9: return
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 this LOuter$Inner;</init>
我們知道, 如果在一個類中, 不聲明構造方法的話, 編譯器會默認添加一個無參數的構造方法。 但是這句話在這里就行不通了, 因為我們明明看到, 這個構造函數有一個構造方法, 並且類型為Outer。 所以說,
編譯器會為內部類的構造方法添加一個參數, 參數的類型就是外部類的類型。
下面我們看看在構造參數中如何使用這個默認添加的參數。 我們來分析一下構造方法的位元組碼。 下面是每行位元組碼的意義:
aload_0 :
將局部變數表中的第一個引用變數載入到操作數棧。 這里有幾點需要說明。
局部變數表中的變數在方法執行前就已經初始化完成;局部變數表中的變數包括方法的參數;成員方法的局部變數表中的第一個變數永遠是this;操作數棧就是
執行當前代碼的棧。所以這句話的意思是: 將this引用從局部變數表載入到操作數棧。
aload_1:
將局部變數表中的第二個引用變數載入到操作數棧。 這里載入的變數就是構造方法中的Outer類型的參數。
putfield #10 // Field this$0:LOuter;
使用操作數棧頂端的引用變數為指定的成員變數賦值。 這里的意思是將外面傳入的Outer類型的參數賦給成員變數this$0 。
這一句putfield位元組碼就揭示了, 指向外部類對象的這個引用變數是如何賦值的。
下面幾句位元組碼和本文討論的話題無關, 只做簡單的介紹。 下面幾句位元組碼的含義是: 使用this引用調用父類(Object)的構造方法然後返回。
用我們比較熟悉的形式翻譯過來, 這個內部類和它的構造函數有點像這樣: (注意, 這里不符合Java的語法, 只是為了說明問題)
?
1
2
3
4
5
6
7
8
class Outer$Inner{
final Outer this$0;
public Outer$Inner(Outer outer){
this.this$0 = outer;
super();
}
}
說到這里, 可以推想到, 在調用內部類的構造器初始化內部類對象的時候, 編譯器默認也傳入外部類的引用。 調用形式有點像這樣: (注意, 這里不符合java的語法, 只是為了說明問題)
vcq9ysfP4M2stcShoyDU2sTasr//wOC1xLPJ1LGx5MG/b3V0ZXJGaWVsZKOsIM/Cw++NDQtcSjugo8YnI+Cgo8cHJlIGNsYXNzPQ=="brush:java;">
void InnerMethod();
flags:
Code:
stack=1, locals=2, args_size=1
0: aload_0
1: getfield #10 // Field this$0:LOuter;
4: getfield #20 // Field
Outer.outerField:I
7: istore_1
8: return
getfield #10 // Field this$0:LOuter;
將成員變數this$0載入到操作數棧上來
getfield #20 // Field Outer.outerField:I
使用上面載入的this$0引用, 將外部類的成員變數outerField載入到操作數棧
istore_1
將操作數棧頂端的int類型的值保存到局部變數表中的第二個變數上(注意, 第一個局部變數被this佔用,
第二個局部變數是i)。操作數棧頂端的int型變數就是上一步載入的outerField變數。 所以, 這句位元組碼的含義就是:
使用outerField為i賦值。
上面三步就是內部類中是如何通過指向外部類對象的引用, 來訪問外部類成員的。
文章寫到這里, 相信讀者對整個原理就會有一個清晰的認識了。 下面做一下總結:
本文通過反編譯內部類的位元組碼, 說明了內部類是如何訪問外部類對象的成員的,除此之外, 我們也對編譯器的行為有了一些了解, 編譯器在編譯時會自動加上一些邏輯, 這正是我們感覺困惑的原因。
關於內部類如何訪問外部類的成員, 分析之後其實也很簡單, 主要是通過以下幾步做到的:
1 編譯器自動為內部類添加一個成員變數, 這個成員變數的類型和外部類的類型相同, 這個成員變數就是指向外部類對象的引用;
2 編譯器自動為內部類的構造方法添加一個參數, 參數的類型是外部類的類型, 在構造方法內部使用這個參數為1中添加的成員變數賦值;
3 在調用內部類的構造函數初始化內部類對象時, 會默認傳入外部類的引用。
H. 深入理解Java虛擬機的目錄
前言
致謝
第一部分 走近Java
第1章 走近Java / 2
1.1 概述 / 2
1.2 Java技術體系 / 3
1.3 Java發展史 / 5
1.4 展望Java技術的未來 / 9
1.4.1 模塊化 / 9
1.4.2 混合語言 / 9
1.4.3 多核並行 / 11
1.4.4 進一步豐富語法 / 12
1.4.5 64位虛擬機 / 13
1.5 實戰:自己編譯JDK / 13
1.5.1 獲取JDK源碼 / 13
1.5.2 系統需求 / 14
1.5.3 構建編譯環境 / 15
1.5.4 准備依賴項 / 17
1.5.5 進行編譯 / 18
1.6 本章小結 / 21
第二部分 自動內存管理機制
第2章 Java內存區域與內存溢出異常 / 24
2.1 概述 / 24
2.2 運行時數據區域 / 25
2.2.1 程序計數器 / 25
2.2.2 Java虛擬機棧 / 26
2.2.3 本地方法棧 / 27
2.2.4 Java堆 / 27
2.2.5 方法區 / 28
2.2.6 運行時常量池 / 29
2.2.7 直接內存 / 29
2.3 對象訪問 / 30
2.4 實戰:OutOfMemoryError異常 / 32
2.4.1 Java堆溢出 / 32
2.4.2 虛擬機棧和本地方法棧溢出 / 35
2.4.3 運行時常量池溢出 / 38
2.4.4 方法區溢出 / 39
2.4.5 本機直接內存溢出 / 41
2.5 本章小結 / 42
第3章 垃圾收集器與內存分配策略 / 43
3.1 概述 / 43
3.2 對象已死? / 44
3.2.1 引用計數演算法 / 44
3.2.2 根搜索演算法 / 46
3.2.3 再談引用 / 47
3.2.4 生存還是死亡? / 48
3.2.5 回收方法區 / 50
3.3 垃圾收集演算法 / 51
3.3.1 標記 -清除演算法 / 51
3.3.2 復制演算法 / 52
3.3.3 標記-整理演算法 / 54
3.3.4 分代收集演算法 / 54
3.4 垃圾收集器 / 55
3.4.1 Serial收集器 / 56
3.4.2 ParNew收集器 / 57
3.4.3 Parallel Scavenge收集器 / 59
3.4.4 Serial Old收集器 / 60
3.4.5 Parallel Old收集器 / 61
3.4.6 CMS收集器 / 61
3.4.7 G1收集器 / 64
3.4.8 垃圾收集器參數總結 / 64
3.5 內存分配與回收策略 / 65
3.5.1 對象優先在Eden分配 / 66
3.5.2 大對象直接進入老年代 / 68
3.5.3 長期存活的對象將進入老年代 / 69
3.5.4 動態對象年齡判定 / 71
3.5.5 空間分配擔保 / 73
3.6 本章小結 / 75
第4章 虛擬機性能監控與故障處理工具 / 76
4.1 概述 / 76
4.2 JDK的命令行工具 / 76
4.2.1 jps:虛擬機進程狀況工具 / 79
4.2.2 jstat:虛擬機統計信息監視工具 / 80
4.2.3 jinfo:Java配置信息工具 / 82
4.2.4 jmap:Java內存映像工具 / 82
4.2.5 jhat:虛擬機堆轉儲快照分析工具 / 84
4.2.6 jstack:Java堆棧跟蹤工具 / 85
4.3 JDK的可視化工具 / 87
4.3.1 JConsole:Java監視與管理控制台 / 88
4.3.2 VisualVM:多合一故障處理工具 / 96
4.4 本章小結 / 105
第5章 調優案例分析與實戰 / 106
5.1 概述 / 106
5.2 案例分析 / 106
5.2.1 高性能硬體上的程序部署策略 / 106
5.2.2 集群間同步導致的內存溢出 / 109
5.2.3 堆外內存導致的溢出錯誤 / 110
5.2.4 外部命令導致系統緩慢 / 112
5.2.5 伺服器JVM進程崩潰 / 113
5.3 實戰:Eclipse運行速度調優 / 114
5.3.1 調優前的程序運行狀態 / 114
5.3.2 升級JDK 1.6的性能變化及兼容問題 / 117
5.3.3 編譯時間和類載入時間的優化 / 122
5.3.4 調整內存設置控制垃圾收集頻率 / 126
5.3.5 選擇收集器降低延遲 / 130
5.4 本章小結 / 133
第三部分 虛擬機執行子系統
第6章 類文件結構 / 136
6.1 概述 / 136
6.2 無關性的基石 / 136
6.3 Class類文件的結構 / 138
6.3.1 魔數與Class文件的版本 / 139
6.3.2 常量池 / 141
6.3.3 訪問標志 / 147
6.3.4 類索引、父類索引與介面索引集合 / 148
6.3.5 欄位表集合 / 149
6.3.6 方法表集合 / 153
6.3.7 屬性表集合 / 155
6.4 Class文件結構的發展 / 168
6.5 本章小結 / 170
第7章 虛擬機類載入機制 / 171
7.1 概述 / 171
7.2 類載入的時機 / 172
7.3 類載入的過程 / 176
7.3.1 載入 / 176
7.3.2 驗證 / 178
7.3.3 准備 / 181
7.3.4 解析 / 182
7.3.5 初始化 / 186
7.4 類載入器 / 189
7.4.1 類與類載入器 / 189
7.4.2 雙親委派模型 / 191
7.4.3 破壞雙親委派模型 / 194
7.5 本章小結 / 197
第8章 虛擬機位元組碼執行引擎 / 198
8.1 概述 / 198
8.2 運行時棧幀結構 / 199
8.2.1 局部變數表 / 199
8.2.2 操作數棧 / 204
8.2.3 動態連接 / 206
8.2.4 方法返回地址 / 206
8.2.5 附加信息 / 207
8.3 方法調用 / 207
8.3.1 解析 / 207
8.3.2 分派 / 209
8.4 基於棧的位元組碼解釋執行引擎 / 221
8.4.1 解釋執行 / 221
8.4.2 基於棧的指令集與基於寄存器的指令集 / 223
8.4.3 基於棧的解釋器執行過程 / 224
8.5 本章小結 / 230
第9章 類載入及執行子系統的案例與實戰 / 231
9.1 概述 / 231
9.2 案例分析 / 231
9.2.1 Tomcat:正統的類載入器架構 / 232
9.2.2 OSGi:靈活的類載入器架構 / 235
9.2.3 位元組碼生成技術與動態代理的實現 / 238
9.2.4 Retrotranslator:跨越JDK版本 / 242
9.3 實戰:自己動手實現遠程執行功能 / 246
9.3.1 目標 / 246
9.3.2 思路 / 247
9.3.3 實現 / 248
9.3.4 驗證 / 255
9.4 本章小結 / 256
第四部分 程序編譯與代碼優化
第10章 早期(編譯期)優化 / 258
10.1 概述 / 258
10.2 Javac編譯器 / 259
10.2.1 Javac的源碼與調試 / 259
10.2.2 解析與填充符號表 / 262
10.2.3 註解處理器 / 264
10.2.4 語義分析與位元組碼生成 / 264
10.3 Java語法糖的味道 / 268
10.3.1 泛型與類型擦除 / 268
10.3.2 自動裝箱、拆箱與遍歷循環 / 273
10.3.3 條件編譯 / 275
10.4 實戰:插入式註解處理器 / 276
10.4.1 實戰目標 / 276
10.4.2 代碼實現 / 277
10.4.3 運行與測試 / 284
10.4.4 其他應用案例 / 286
10.5 本章小結 / 286
第11章 晚期(運行期)優化 / 287
11.1 概述 / 287
11.2 HotSpot虛擬機內的即時編譯器 / 288
11.2.1 解釋器與編譯器 / 288
11.2.2 編譯對象與觸發條件 / 291
11.2.3 編譯過程 / 294
11.2.4 查看與分析即時編譯結果 / 297
11.3 編譯優化技術 / 301
11.3.1 優化技術概覽 / 301
11.3.2 公共子表達式消除 / 305
11.3.3 數組邊界檢查消除 / 307
11.3.4 方法內聯 / 307
11.3.5 逃逸分析 / 309
11.4 Java與C/C++的編譯器對比 / 311
11.5 本章小結 / 313
第五部分 高效並發
第12章 Java內存模型與線程 / 316
12.1 概述 / 316
12.2 硬體的效率與一致性 / 317
12.3 Java內存模型 / 318
12.3.1 主內存與工作內存 / 319
12.3.2 內存間交互操作 / 320
12.3.3 對於volatile型變數的特殊規則 / 322
12.3.4 對於long和double型變數的特殊規則 / 327
12.3.5 原子性、可見性與有序性 / 328
12.3.6 先行發生原則 / 330
12.4 Java與線程 / 333
12.4.1 線程的實現 / 333
12.4.2 Java線程調度 / 337
12.4.3 狀態轉換 / 339
12.5 本章小結 / 341
第13章 線程安全與鎖優化 / 342
13.1 概述 / 342
13.2 線程安全 / 343
13.2.1 Java語言中的線程安全 / 343
13.2.2 線程安全的實現方法 / 348
13.3 鎖優化 / 356
13.3.1 自旋鎖與自適應自旋 / 356
13.3.2 鎖消除 / 357
13.3.3 鎖粗化 / 358
13.3.4 輕量級鎖 / 358
13.3.5 偏向鎖 / 361
13.4 本章小結 / 362
附錄A Java虛擬機家族 / 363
附錄B 虛擬機位元組碼指令表 / 366
附錄C HotSpot虛擬機主要參數表 / 372
附錄D 對象查詢語言(OQL)簡介 / 376
附錄E JDK歷史版本軌跡 / 383
I. 用java代碼調用虛擬列印將DOC轉PDF,可是,當多人同時訪問調用時候,只能轉化成功一個,我改怎麼解決
您好
Java虛擬機是一個想像中的機器,在實際的計算機上通過軟體模擬來實現。Java虛擬機有自己想像中的硬體,如處理器、堆棧、寄存器等,還具有相應的指令系統。
1.為什麼要使用Java虛擬機
Java語言的一個非常重要的特點就是與平台的無關性。而使用Java虛擬機是實現這一特點的關鍵。一般的高級語言如果要在不同的平台上運行,至少需要編譯成不同的目標代碼。而引入Java語言虛擬機後,Java語言在不同平台上運行時不需要重新編譯。Java語言使用模式Java虛擬機屏蔽了與具體平台相關的信息,使得Java語言編譯程序只需生成在Java虛擬機上運行的目標代碼(位元組碼),就可以在多種平台上不加修改地運行。Java虛擬機在執行位元組碼時,把位元組碼解釋成具體平台上的機器指令執行。
2.誰需要了解Java虛擬機
Java虛擬機是Java語言底層實現的基礎,對Java語言感興趣的人都應對Java虛擬機有個大概的了解。這有助於理解Java語言的一些性質,也有助於使用Java語言。對於要在特定平台上實現Java虛擬機的軟體人員,Java語言的編譯器作者以及要用硬體晶元實現Java虛擬機的人來說,則必須深刻理解Java虛擬機的規范。另外,如果你想擴展Java語言,或是把其它語言編譯成Java語言的位元組碼,你也需要深入地了解Java虛擬機。
J. 深入理解java虛擬機應屆生需要理解到什麼程度
從進程的角度解釋JVM
讓我們嘗試從操作系統的層面來理解虛擬機。我們知道,虛擬機是運行在操作系統之中的,那麼什麼東西才能在操作系統中運行呢?當然是進程,因為進程是操作系統中的執行單位。可以這樣理解,當它在運行的時候,它就是一個操作系統中的進程實例,當它沒有在運行時(作為可執行文件存放於文件系統中),可以把它叫做程序。
對命令行比較熟悉的同學,都知道其實一個命令對應一個可執行的二進制文件,當敲下這個命令並且回車後,就會創建一個進程,載入對應的可執行文件到進程的地址空間中,並且執行其中的指令。下面對比C語言和Java語言的HelloWorld程序來說明問題。
首先編寫C語言版的HelloWorld程序。
[cpp] view plain
#include <stdio.h>
#include <stdlib.h>
int main(void) {
printf("hello world\n");
return 0;
}
編譯C語言版的HelloWorld程序:
[plain] view plain
gcc HelloWorld.c -o HelloWorld
運行C語言版的HelloWorld程序:
[plain] view plain
zhangjg@linux:/deve/workspace/HelloWorld/src$ ./HelloWorld
hello world
gcc編譯器編譯後的文件直接就是可被操作系統識別的二進制可執行文件,當我們在命令行中敲下 ./HelloWorld這條命令的時候, 直接創建一個進程, 並且將可執行文件載入到進程的地址空間中, 執行文件中的指令。
作為對比, 我們看一下Java版HelloWord程序的編譯和執行形式。
首先編寫源文件HelloWord.java :
[java] view plain
public class HelloWorld {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
}
編譯Java版的HelloWorld程序:
[java] view plain
zhangjg@linux:/deve/workspace/HelloJava/src$ javac HelloWorld.java
zhangjg@linux:/deve/workspace/HelloJava/src$ ls
HelloWorld.class HelloWorld.java
運行Java版的HelloWorld程序:
[plain] view plain
zhangjg@linux:/deve/workspace/HelloJava/src$ java -classpath . HelloWorld
HelloWorld
從上面的過程可以看到, 我們在運行Java版的HelloWorld程序的時候, 敲入的命令並不是 ./HelloWorld.class 。 因為class文件並不是可以直接被操作系統識別的二進制可執行文件 。 我們敲入的是java這個命令。 這個命令說明, 我們首先啟動的是一個叫做java的程序, 這個java程序在運行起來之後就是一個JVM進程實例。
上面的命令執行流程是這樣的:
java命令首先啟動虛擬機進程,虛擬機進程成功啟動後,讀取參數「HelloWorld」,把他作為初始類載入到內存,對這個類進行初始化和動態鏈接(關於類的初始化和動態鏈接會在後面的博客中介紹),然後從這個類的main方法開始執行。也就是說我們的.class文件不是直接被系統載入後直接在cpu上執行的,而是被一個叫做虛擬機的進程託管的。首先必須虛擬機進程啟動就緒,然後由虛擬機中的類載入器載入必要的class文件,包括jdk中的基礎類(如String和Object等),然後由虛擬機進程解釋class位元組碼指令,把這些位元組碼指令翻譯成本機cpu能夠識別的指令,才能在cpu上運行。
從這個層面上來看,在執行一個所謂的java程序的時候,真真正正在執行的是一個叫做Java虛擬機的進程,而不是我們寫的一個個的class文件。這個叫做虛擬機的進程處理一些底層的操作,比如內存的分配和釋放等等。我們編寫的class文件只是虛擬機進程執行時需要的「原料」。這些「原料」在運行時被載入到虛擬機中,被虛擬機解釋執行,以控制虛擬機實現我們java代碼中所定義的一些相對高層的操作,比如創建一個文件等,可以將class文件中的信息看做對虛擬機的控制信息,也就是一種虛擬指令。