国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

逐夢offer -- JVM篇

greatwhole / 2885人閱讀

摘要:的字節碼解釋器和編譯器使用寫屏障維護卡表。解釋器每次執行更新引用的字節碼時,都會執行一段寫屏障,編譯器在生成更新引用的代碼后,也會生成一段寫屏障。

4. JVM 4.1 GC 1. 垃圾收集

基礎 : 可達性分析算法 GC ROOTS

復制算法

標記清除

標記整理

分代收集 -- 1. 新生代 ; 2.3 老年代
注: Oop Map -- 安全點 -- 安全區

以下部分內容 來自 這個博主的文章

1. 3種基本算法

標記清除法/標記壓縮法、復制收集算法、引用計數法

這里的 引用計數法 因為書中講解少,所以講一下:
引用計數法,它的基本原理是,在每個對象中保存該對象的引用計數,當引用發生增減時對計數進行更新。引用計數的增減,一般發生在變量賦值、對象內容更新、函數結束(局部變量不再被引用)等時間點。當一個對象的引用計數變為0時,則說明它將來不會再被引用,因此可以釋放相應的內存空間。
缺點:

無法釋放循環引用的對象。

必須在引用發生增減時對引用計數做出正確的增減,而如果漏掉了某個增減的話,就會引發很難找到原因的內存錯誤。引用數忘了增加的話,會對不恰當的對象進行釋放;而引用數忘了減少的話,對象會一直殘留在內存中,從而導致內存泄漏。

引用計數管理并不適合并行處理: 就如同 ConcurrenHashMap源碼分析 中的算法一樣,無法在并行情況下對數量進行準確的計算。

2. 3種進階算法

分代回收
分代回收的目的,正是為了在程序運行期間,將GC所消耗的時間盡量縮短。

分代回收的基本思路,是利用了一般性程序所具備的性質,即大部分對象都會在短時間內成為垃圾,而經過一定時間依然存活的對象往往擁有較長的壽命。
HotSpot 虛擬機中,在新生代用復制算法,老年代使用標記清除/整理算法。

問題:如果存在老生代對象對新生代對象的引用。如果只掃描新生代區域的話,那么從老生代對新生代的引用就不會被檢測到。
這樣一來,如果一個年輕的對象只有來自老生代對象的引用,就會被誤認為已經“死亡”了。
因此,在分代回收中,會對對象的更新進行監視,將從老生代對新生代的引用,
記錄在一個叫做記錄集 Rset(remembered set)的表中。在執行小回收(Minor Gc)的過程中,這個記錄集也作為一個根來對待。

解決方案:在老生代到新生代的引用產生的瞬間,就必須對該引用進行記錄,而負責執行這個操作的子程序,需要被嵌入到所有涉及對象更新操作的地方。
這個負責記錄引用的子程序是這樣工作的。設有兩個對象:A和B,當對A的內容進行改寫,并加入對B的引用時,
如果①A屬于老生代對象,②B屬于新生代對象,則將該引用添加到記錄集中。
這種檢查程序需要對所有涉及修改對象內容的地方進行保護,因此被稱為寫屏障(Write barrier)

增量回收
為了維持程序的實時性,不等到GC全部完成,而是將GC操作細分成多個部分逐一執行。這種方式被稱為增量回收

并行回收
并行回收的基本原理是,是在原有的程序運行的同時進行GC操作,這一點和增量回收是相似的。

不過,相對于在一個CPU上進行GC任務分割的增量回收來說,并行回收可以利用多CPU的性能,盡可能讓這些GC任務并行(同時)進行。

3. Card Table 數據結構

為了支持高頻率的新生代的回收,虛擬機使用一種叫做卡表(Card Table)的數據結構.
卡表作為一個比特位的集合,每一個比特位可以用來表示年老代的某一區域中的所有對象是否持有新生代對象的引用。

一、作用
卡表中每一個位表示年老代4K的空間,
卡表記錄為 0 的年老代區域沒有任何對象指向新生代,
卡表記錄為 1 的區域才有對象包含新生代引用,
因此在新生代GC時,只需要掃描卡表位為1所在的年老代空間。使用這種方式,可以大大加快新生代的回收速度。

二、結構
卡表是個單字節數組,每個數組元素對應堆中的一張卡。
每次年老代對象中某個引用新生代的字段發生變化時,Hotspot VM就必須將該卡所對應的卡表元素設置為適當的值,從而將該引用字段所在的卡標記為臟
如下圖:

在Minor GC過程中,垃圾收集器只會在臟卡中掃描查找年老代-新生代引用。

Hotspot VM的字節碼解釋器和JIT編譯器使用寫屏障 維護卡表。
寫屏障 (Write barrier) 是一小段將卡狀態設置為臟的代碼。 解釋器每次執行更新引用的字節碼時,都會執行一段寫屏障,JIT編譯器在生成更新引用的代碼后,也會生成一段寫屏障。
雖然寫屏障使得應用線程增加了 -- 性能開銷,但Minor GC變快了許多,整體的垃圾收集效率也提高了許多,通常應用的吞吐量也會有所改善。

4. 評價指標

1、 吞吐量

應用系統的生命周期內,應用程序所花費的時間和系統總運行時間的比值
系統總運行時間=應用程序耗時+GC耗時
2、 垃圾回收器負載
垃圾回收器負載=GC耗時/系統總運行時間
3、 停頓時間
垃圾回收器運行時,應用程序的暫停時間
4、 垃圾回收頻率
垃圾回收器多長時間運行一次。一般而言,頻率越低越好,通常增大堆空間可以有效降低垃圾回收發生的頻率,但是會增加回收時產生的停頓時間。
5、 反應時間
當一個對象成為垃圾后,多長時間內,它所占用的內存空間會被釋放掉。

2. 內存分配
1. 基礎知識

-Xms 堆大小
-Xmx 可擴展大小
-Xmn 老年代大小
-XX:SurvivorRatio Eden 區與 Survivor 區大小比例
注: surivor 區分為 from 區與 to 區

- 在GC開始的時候,對象只會存在于Eden區和名為“From”的Survivor區,Survivor區“To”是空的。
- 緊接著進行GC,Eden區中所有存活的對象都會被復制到“To”,而在“From”區中,仍存活的對象會根據他們的年齡值來決定去向。
- 年齡達到一定值(年齡閾值,可以通過-XX:MaxTenuringThreshold來設置)的對象會被移動到年老代中,沒有達到閾值的對象會被復制到“To”區域
- 經過這次GC后,Eden區和From區已經被清空。這個時候,“From”和“To”會交換他們的角色,也就是新的“To”就是上次GC前的“From”
- 新的“From”就是上次GC前的“To”。
- 不管怎樣,都會保證名為To的Survivor區域是空的。Minor GC會一直重復這樣的過程,直到“To”區被填滿,“To”區被填滿之后,會將所有對象移動到年老代中。

大對象直接進入老年代 :很長的字符串以及數組

長期存活的對象進入老年代 -XX:MaxTenuringThreshold

動態對象年齡判定 :如果在Survivor 中,相同年齡所有對象的大小總和大于 Survivor 空間的一半, 大于或等于此年齡的對象就可以直接進入老年代。

分配擔保機制

檢查老年代最大可用連續空間 與 新生代所有對象的總空間 --> yes --> MinorGc

HandlePromotionFailure 是否允許擔保失敗 --> yes --> 檢查老年代最大可用連續空間是否大于歷次晉升到老年代對象的平均大小 --> MinorGC

2. Minor GC ,Full GC 觸發條件

Minor GC觸發條件:當Eden區滿時,觸發Minor GC。
Full GC觸發條件:
(1)調用System.gc時,系統建議執行Full GC,但是不必然執行
(2)老年代空間不足
(3)方法去空間不足
(4)通過Minor GC后進入老年代的平均大小大于老年代的可用內存
(5)由Eden區、From Space區向To Space區復制時,對象大小大于To Space可用內存,則把該對象轉存到老年代,且老年代的可用內存小于該對象大小

3. 垃圾收集器
1. CMS (Concurrent Mark Sweep)

4個步驟:

初始標記:標記 GC ROOTS 可以直接關聯的對象

并發標記:GC TRACING

重新標記:修正并發標記期間,用戶程序繼續動作而導致的標記產生變動的那一部分對象的標記記錄

并發清除

3個缺點:

對 CPU 資源非常敏感

無法處理浮動垃圾(并發清理階段,用戶線程仍舊在運行,因此一直在產生垃圾,而無法在當次收集中處理掉它們)

產生大量的空間碎片

2. G1 (Garbage-First)

4個特點:

并行與并發: 使用多個 CPU 或 CPU 核心來縮短 Stop-The-World 停頓的時間

分代收集

空間整合: 基于標記-整理算法

可預測的停頓: 可以建立可預測的停頓時間模型,讓使用者明確指定在一個長度為 M 毫秒的時間片段內,消耗在垃圾收集上的時間不超過 N 毫秒。

4個步驟:

初始標記

并發標記

最終標記

篩選回收: 首先對各個 Region 的回收價值和成本進行排序,根據用戶所期望的 GC 停頓時間來制定回收計劃。

G1的GC模式

Young GC:選定所有年輕代里的Region。通過控制年輕代的region個數,即年輕代內存大小,來控制young GC的時間開銷。
Mixed GC:選定所有年輕代里的Region,外加根據global concurrent marking統計得出收集收益高的若干老年代Region。在用戶指定的開銷目標范圍內盡可能選擇收益高的老年代Region。

注意:Mixed GC不是full GC,它只能回收部分老年代的Region,如果mixed GC實在無法跟上程序分配內存的速度,導致老年代填滿無法繼續進行Mixed GC,就會使用serial old GC(full GC)來收集整個GC heap。

global concurrent marking:類似CMS,為Mixed GC提供標記服務。
四個過程:

初始標記(initial mark,STW)。它標記了從GC Root開始直接可達的對象。

并發標記(Concurrent Marking)。這個階段從GC Root開始對heap中的對象標記,標記線程與應用程序線程并行執行,并且收集各個Region的存活對象信息。

最終標記(Remark,STW)。標記那些在并發標記階段發生變化的對象,將被回收。

清除垃圾(Cleanup)。清除空Region(沒有存活對象的),加入到free list。

G1 中的幾個重要概念 -- 原文鏈接--美團點評

一、Region

傳統的GC收集器將連續的內存空間劃分為新生代、老年代和永久代(JDK 8去除了永久代,引入了元空間Metaspace),這種劃分的特點是各代的存儲地址(邏輯地址,下同)是連續的。

如下圖所示:

而G1的各代存儲地址是不連續的,每一代都使用了n個不連續的大小相同的Region,每個Region占有一塊連續的虛擬內存地址。如下圖所示:

在上圖中,我們注意到還有一些Region標明了H,它代表Humongous,這表示這些Region存儲的是巨大對象(humongous object,H-obj),即大小大于等于region一半的對象。H-obj有如下幾個特征:

H-obj直接分配到了old gen (老年代),防止了反復拷貝移動。

H-obj在global concurrent marking 階段的 cleanupfull GC 階段回收。

在分配H-obj之前先檢查是否超過 initiating heap occupancy percent和the marking threshold, 如果超過的話,就啟動 global concurrent marking,為的是提早回收,防止 evacuation failures 和 full GC。
為了減少連續H-objs分配對GC的影響,需要把大對象變為普通的對象,建議增大Region size。

二、SATB

全稱是Snapshot-At-The-Beginning,由字面理解,是GC開始時活著的對象的一個快照。它是通過Root Tracing得到的,作用是維持并發GC的正確性。

那么它是怎么維持并發GC的正確性的呢?根據三色標記算法,我們知道對象存在三種狀態:

白:對象沒有被標記到,標記階段結束后,會被當做垃圾回收掉。

灰:對象被標記了,但是它的field還沒有被標記或標記完。

黑:對象被標記了,且它的所有field也被標記完了。

由于并發階段的存在,Mutator(更改器和)Garbage Collector線程同時對對象進行修改,就會出現白對象漏標的情況,這種情況發生的前提是:

Mutator賦予一個黑對象該白對象的引用。

Mutator刪除了所有從灰對象到該白對象的直接或者間接引用。

對于第一個條件,在并發標記階段,如果該白對象是new出來的,并沒有被灰對象持有,那么它會不會被漏標呢?Region中有兩個top-at-mark-start(TAMS)指針,分別為prevTAMS和nextTAMS。在TAMS以上的對象是新分配的,這是一種隱式的標記。
對于在GC時已經存在的白對象,如果它是活著的,它必然會被另一個對象引用,即條件二中的灰對象。如果灰對象到白對象的直接引用或者間接引用被替換了,或者刪除了,白對象就會被漏標,從而導致被回收掉,這是非常嚴重的錯誤,所以SATB破壞了第二個條件。
也就是說,一個對象的引用被替換時,可以通過 write barrier 將舊引用記錄下來。(并沒有 看懂在說什么)

SATB也是有副作用的,如果被替換的白對象就是要被收集的垃圾,這次的標記會讓它躲過GC,這就是float garbage。因為SATB的做法精度比較低,所以造成的float garbage也會比較多。

三、RSet

全稱是Remembered Set,是輔助GC過程的一種結構,典型的空間換時間工具,和Card Table有些類似。
還有一種數據結構也是輔助GC的:Collection Set(CSet),它記錄了 GC要收集的Region集合 ,集合里的Region可以是任意年代的。
在GC的時候,對于old->young和old->old的跨代對象引用,只要掃描對應的CSet中的RSet即可。

Rset : 屬于points-into結構(誰引用了我的對象)
Card Table : 則是一種points-out(我引用了誰的對象)的結構
G1的RSet是在Card Table的基礎上實現的:每個Region會記錄下別的Region有指向自己的指針,并標記這些指針分別在哪些Card的范圍內。
這個RSet其實是一個Hash Table,Key -- 別的Region的起始地址Value是一個集合 -- 里面的元素是Card Table的Index

這里解釋一下 :
上圖有三個 Region 。紅色代表 Rset , 灰色大方框代表 Card Table。
Region2 的 Rset2 中有兩個 Region 的起始地址,分別指向 Region1 , Region3。 -- 代表 Region1 與 Region3 引用了我的對象。
Region1 的 Card Table 位置上,存在一個 對 Region2 的引用。 -- 代表 Region1 引用了 Region2 的對象。
Region3 同理。

作用:
在做YGC(Minor GC)的時候,只需要選定young generation region的RSet作為根集,這些RSet記錄了old->young的跨代引用,避免了掃描整個old generation。
而mixed gc的時候,old generation中記錄了old->old的RSet,young->old的引用由掃描全部young generation region得到,這樣也不用掃描全部old generation region。所以RSet的引入大大減少了GC的工作量。

四、Pause Prediction Model

G1 uses a pause prediction model to meet a user-defined pause time target and selects the number of regions to collect based on the specified pause time target.

G1 GC是一個響應時間優先的GC算法,它與CMS最大的不同是,用戶可以設定整個GC過程的期望停頓時間,參數"-XX:MaxGCPauseMillis"指定一個G1收集過程目標停頓時間,默認值200ms。
G1 通過這個模型統計計算出來的歷史數據來預測本次收集需要選擇的Region數量,從而盡量滿足用戶設定的目標停頓時間。
停頓預測模型是以衰減標準偏差為理論基礎實現的。
這里就不詳細介紹了,有興趣的,可以看 美團大神的文章

4.2 Java 內存

程序計數器

虛擬機棧 : 局部變量表、操作數棧、動態鏈接、方法出口

本地方法棧 : native 方法

堆 : 所有的對象實例以及數組

方法區 : 已被加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼

運行時常量池 : 編譯期生成的各種字面量和符號引用

直接內存 : NIO類引入了一種基于通道(channel) 與 緩沖區(buffer) 的 I/O 方式,使用 Native 函數庫直接分配堆外內存 , 通過存儲在 Java 堆中的 DirectByteBuffer 對象作為這塊內存的引用進行操作。

1. Java 對象的內存布局

對象頭 : 哈希碼(2bit)-分代年齡(4)、輕量級鎖定(標志位 00)、重量級鎖定、GC標記、可偏向(標志位 01)補充: 類型指針、數組長度

實例數據 :

對齊填充

2. OOM 異常

堆溢出: 不斷創建對象,并且存在可達路徑,不被清除。那么對象在達到最大堆容量限制后就會產生內存溢出
通過 內存映像分析工具 (Eclipse Memory Analyzer) 對 Dump 出來的堆轉存儲快照進行分析。判斷是內存泄漏還是內存溢出。

虛擬機棧與本地方法棧溢出:
如果線程請求的棧深度大于虛擬機所允許的最大深度,將拋出 StackOverFlowError 異常。

如果虛擬機在擴展棧時無法申請到足夠的內存空間,則拋出 OutOfMemoryError 異常。

方法區
方法區存放 Class 的相關信息。如果存在大量的類 填滿 方法區。則會產生溢出。

通過 動態代理 或 通過 CGLIB 動態生成大量的類,以及大量 JSP與 動態JSP 文件的應用 。

3. OOM 異常的解決

一. 可通過命令定期抓取heap dump或者啟動參數OOM時自動抓取heap dump文件。
二. 通過對比多個heap dump,以及heap dump的內容,分析代碼找出內存占用最多的地方。
三. 分析占用的內存對象,是否是因為錯誤導致的內存未及時釋放,或者數據過多導致的內存溢出。

4.3 類加載器 1. 類加載過程

加載 :可以通過自定義類加載器參與

通過一個類的全限定名獲取定義此類的二進制字節流

將這個字節流代表的靜態存儲結構轉化為方法區的運行時數據結構

在內存中生成一個代表這個類的 java.lang.Class 對象,作為方法區這個類的各種數據的訪問入口

驗證

文件格式驗證

元數據驗證 : 語義校驗

字節碼驗證 :邏輯校驗

符號引用驗證 :發生在解析階段中,將符號引用轉化為直接引用

準備 : 為類變量分配內存并設置類變量初始值的階段

解析 : 將符號引用 替換 為直接引用的過程。

初始化 : () 類構造器 : 將類中的賦值語句與靜態代碼塊合并而成 -- () 實例構造器

2. 雙親委派模型

  啟動(Bootstrap)類加載器:采用 C++ 實現,它負責將 /lib下面的核心類庫或-Xbootclasspath選項指定的jar包加載到內存中。由于啟動類加載器到本地代碼的實現,開發者無法直接獲取到啟動類加載器的引用,所以不允許直接通過引用進行操作。編寫自定義類加載器時,如果需要把加載請求委派給啟動類加載器,直接使用 null 代替.
  擴展(Extension)類加載器:擴展類加載器是由Sun的ExtClassLoader(sun.misc.Launcher$ExtClassLoader)實現的。它負責將< Java_Runtime_Home >/lib/ext或者由系統變量-Djava.ext.dir指定位置中的類庫加載到內存中。開發者可以直接使用標準擴展類加載器。
  系統(System)類加載器:系統類加載器是由 Sun的 AppClassLoader(sun.misc.Launcher$AppClassLoader)實現的。它負責將系統類路徑java -classpath或-Djava.class.path變量所指的目錄下的類庫加載到內存中。開發者可以直接使用系統類加載器。

工作過程:
如果一個類加載器收到了類的加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成。直到頂層的啟動類加載器中,當父加載器反饋自己無法完成這個加載請求時,子加載器會嘗試自己去加載。

3. 線程上下文類加載器

方便 JNDI 服務:SPI 的接口是 Java 核心庫的一部分,是由引導類加載器來加載的;SPI 實現的 Java 類一般是由系統類加載器來加載的。引導類加載器是無法找到 SPI 的實現類的,因為它只加載 Java 的核心庫。它也不能代理給系統類加載器,因為它是系統類加載器的祖先類加載器。也就是說,類加載器的代理模式無法解決這個問題。
解決方法:Java 應用的線程的上下文類加載器 默認 就是系統上下文類加載器。在 SPI 接口的代碼中使用線程上下文類加載器,就可以成功的加載到 SPI 實現的類。線程上下文類加載器在很多 SPI 的實現中都會用到。
Java默認的線程上下文類加載器是系統類加載器(AppClassLoader)。以下代碼摘自sun.misc.Launch的無參構造函數Launch()。
可以通過 java.lang.Thread類 的 setContextClassLoader() 設置。

4. OSGI(open service gataway initiative)

方便執部署的實現。可以在不重啟服務器的情況下,對其中的邏輯代碼進行更新。
由 父類加載器 與 Bundle 組成 , 每個 Bundle 的功能都是 發布 export 與依賴 import。從而形成復雜的網狀結構
原理:
OSGi 中的每個模塊都有對應的一個類加載器。它負責加載模塊自己包含的 Java 包和類。
當它需要加載 Java 核心庫的類時(以 java開頭的包和類),它會代理給父類加載器(通常是啟動類加載器)來完成。
當它需要加載所導入的 Java 類時,它會代理給導出此 Java 類的模塊來完成加載。

5. Tomcat

在雙親委派模型的基礎上加入了 Common類加載器,Catalina類加載器,Shared類加載器,WebApp類加載器,Jsp類加載器
Common類加載器, /common 目錄 被 Tomcat 與 所以 Web 應用程序共同使用
Catalina類加載器, /server 目錄中, 被 Tomcat 使用
Shared類加載器, /shared 目錄中 ,被所有 Web 應用程序共同使用
WebApp類加載器,Jsp類加載器 , /WebApp/WEB-INF 目錄中,只能被此 Web 應用程序使用。

4.4 解釋器與編譯器 1. 編譯模式

Mixed Mode -- 混合模式
默認為混合模式,解釋器與編譯器搭配使用。

Interpreted Mode -- 解釋模式
使用 “-Xint" 參數。只使用解釋。

Compiled Mode -- 編譯模式
使用 “-Xcomp" 參數。 優先采用編譯,當編譯無法進行時,使用解釋。

-version 命令,可以輸出顯示這三種模式

2. 分層編譯(Tiered Compilation)

JDK1.7 中的 Server 模式虛擬機中被作為默認編譯策略。

0層,程序解釋執行,解釋器不開啟性能監控功能(Profiling),可觸發第一層編譯

1層,也叫C1 編譯(下文有解釋),將字節碼編譯為本地代碼,進行簡單、可靠的優化

2層,C2編譯。

3. OSR編譯

因為存在多次執行的循環體,所以觸發 OSR 編譯,以整個方法 作為編譯對象。
發生在方法執行過程中,所以叫( On Stack Replacement ) 方法棧幀還在棧上,方法就被替換了。

4. 編譯對象以及觸發條件

熱點代碼的分類:

被多次調用的方法

被多次執行的方法體 -- OSR 編譯

熱點探測(Hot Spot Detection)

基于采樣 : 如果周期性的檢查各個線程的棧頂,如果發現某個方法經常出現在棧頂,則這個方法就是“熱點方法”。

基于計數器 -- HotSpot 虛擬機中采用。

原理: 為每個方法建立計數器,統計方法的次數,如果執行次數超過一定的閾值,就認為它是“熱點方法”

計數器分類:

方法調用計數器(Invocation Counter) :

**統計一段時間內**,方法被調用的次數,如果超過時間限度,則將這個方法的調用計數器減少一半,稱為**衰減**

回邊計數器(Back Edge Counter) : 統計一個方法中循環體被執行的次數 -- OSR 編譯

在字節碼中遇到控制流向后跳轉的指令,稱為回邊。

5. 優化措施

hotspot中內嵌有2個JIT編譯器,分別為Client Compiler,Server Compiler,但大多數情況下我們稱之為C1編譯器和C2編譯器。

5.1 C1 編譯器

client compiler,又稱C1編譯器,較為輕量,只做少量性能開銷比較高的優化,它占用內存較少,適合于桌面交互式應用。
在寄存器分配策略上,JDK6以后采用的為線性掃描寄存器分配算法,其他方面的優化,主要有方法內聯、去虛擬化、冗余消除等。

A、方法內聯

多個方法調用,執行時要經歷多次參數傳遞,返回值傳遞及跳轉等,C1采用方法內聯,把調用到的方法的指令直接植入當前方法中。-XX:+PringInlining來查看方法內聯信息,-XX:MaxInlineSize=35控制編譯后文件大小。

B、去虛擬化

是指在裝載class文件后,進行類層次的分析,如果發現類中的方法只提供一個實現類,那么對于調用了此方法的代碼,也可以進行方法內聯,從而提升執行的性能。

C、冗余消除

在編譯時根據運行時狀況進行代碼折疊或消除。

5.2 C2 編譯器

Server compiler,稱為C2編譯器,較為重量,采用了大量傳統編譯優化的技巧來進行優化,占用內存相對多一些,適合服務器端的應用。和C1的不同主要在于寄存器分配策略及優化范圍.
寄存器分配策略上C2采用的為傳統的圖著色寄存器分配算法,由于C2會收集程序運行信息,因此其優化范圍更多在于全局優化,不僅僅是一個方塊的優化。
收集的信息主要有:分支的跳轉/不跳轉的頻率、某條指令上出現過的類型、是否出現過空值、是否出現過異常等

逃逸分析(Escape Analysis) 是C2進行很多優化的基礎,它根據運行狀態來判斷方法中的變量是否會被外部讀取,如不會則認為此變量是不會逃逸的,那么在編譯時會做標量替換、棧上分配和同步消除等優化。
如果證明一個對象不會逃逸到方法或線程之外,則:

- 棧上分配(Stack Allocation) :確定不會逃逸到**方法外**,讓這個對象在棧上分配內存,對象占用的內存空間可以隨棧幀的出棧而銷毀。
- 同步消除(Synchronization Elimination) :確定不會逃逸到**線程外**,則無法被其他線程訪問,所以可以取消同步措施。
- 標量替換(Scalar Repalcement) : 
    標量(Scalar)指一個數據無法再分解成更小的數據來表示 -- Java 中的原始數據類型
    聚合量(Aggregate)指一個數據可以繼續分解 -- Java 中的對象
    **原理:**直接創建若干個可以被方法使用的成員變量來替代。
5.3 其他措施(注: 不知是 C1 還是 C2)

語言無關的經典優化技術 -- 公共子表達式消除(Common Subexpression Elimination)

如果一個表達式E 已經計算過,并且從先前的計算 到現在 值未曾改變,那么如果 E 再次出現,則可以直接使用之前的表達式結果,代替 E 。

語言相關的經典優化技術 -- 數組邊界檢查消除(Array Bounds Checking Elimination)
這個不是很了解,做一個重點。。。 以后整理

4. 零散知識點 1. 靜態多分派與動態單分派

靜態分派 : 依靠靜態類型 定位方法。
編譯階段:Human man = new Man(); // 靜態類型為 Human
運行階段:man.sayHello() // 動態類型為 Man

重載的優先級
sayHello(char arg);
char -> int -> long -> float -> double // 不可轉化為 byte short , 因為char 轉化是不安全的。
-> Character -> Serializable/Comparable -> Object -> char...(變長參數)

宗量:方法的接收者與方法的參數統稱為宗量
單分派 根據一個宗量對目標方法進行選擇
多分派 根據多個宗量對目標方法進行選擇

public class QQ{};
public class _360{};
public static class Father {
    public void hardChoice(QQ arg);
    public void hardChoice(_360 arg);
}
public static class Son extends Father{
    public void hardChoice(QQ arg);
    public void hardChoice(_360 arg);
}

Father father = new Father();
Father son = new Son();

// 靜態多分派 - 編譯 : 方法的接收者 Father - Son, 參數 QQ - _360
father.hardChoice(_360);
// 動態多分派 - 運行 : 已經確定 參數為 QQ ,再判斷 實際類型 , son的實際類型為 Son 。
son.hardChoice(QQ);
結語

都看到這里了,點個關注,點波再走,QAQ。
你的小手輕點,是我最大的動力哦。

一只想當程序員的1米88處女座大可愛如此說道。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67768.html

相關文章

  • 跨越逐夢路上的荊棘(程序猿生存)

    摘要:曾經的小學生,初中生現如今已是社會的中流砥柱。一個互聯網公司要正常運作,必定就需要一群足智多謀,思維敏捷,邏輯縝密的程序猿。這群能力超凡的人類,其實也有不堪一擊的致命弱點。同時我們也該擁有同等的尊重。 時光荏苒,歲月如梭。曾經的小學生,初中生現如今已是社會的中流砥柱。隨著科技時代的迅猛發展,曾經的荒土,已是星羅棋布高樓聳立。其中不乏科技相關的樓宇,俗稱互聯網公司。也許你,現在就正處于其...

    CastlePeaK 評論0 收藏0
  • 跨越逐夢路上的荊棘(程序猿生存)

    摘要:曾經的小學生,初中生現如今已是社會的中流砥柱。一個互聯網公司要正常運作,必定就需要一群足智多謀,思維敏捷,邏輯縝密的程序猿。這群能力超凡的人類,其實也有不堪一擊的致命弱點。同時我們也該擁有同等的尊重。 時光荏苒,歲月如梭。曾經的小學生,初中生現如今已是社會的中流砥柱。隨著科技時代的迅猛發展,曾經的荒土,已是星羅棋布高樓聳立。其中不乏科技相關的樓宇,俗稱互聯網公司。也許你,現在就正處于其...

    Barry_Ng 評論0 收藏0
  • 2017-10-16 前端日報

    摘要:前端日報精選譯發布了王躍關于微信小程序的技術,也許你想錯了細說中的瀏覽器頁面渲染工作原理淺析騰訊前端團隊社區中文第期安息吧,長存譯借助函數完成可組合的數據類型軟件編寫第十部分掘金對象與原型掘金技術周刊期知乎專欄是真正的語言 2017-10-16 前端日報 精選 [譯]Vue 2.5 發布了王躍:關于微信小程序的技術,也許你想錯了細說Web API中的Blobchrome瀏覽器頁面渲染工...

    molyzzx 評論0 收藏0
  • 我的阿里之路+Java面經考點

    摘要:我的是忙碌的一年,從年初備戰實習春招,年三十都在死磕源碼,三月份經歷了阿里五次面試,四月順利收到實習。因為我心理很清楚,我的目標是阿里。所以在收到阿里之后的那晚,我重新規劃了接下來的學習計劃,將我的短期目標更新成拿下阿里轉正。 我的2017是忙碌的一年,從年初備戰實習春招,年三十都在死磕JDK源碼,三月份經歷了阿里五次面試,四月順利收到實習offer。然后五月懷著忐忑的心情開始了螞蟻金...

    姘擱『 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<