最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JVM:早期(編譯期)優(yōu)化的深入理解

 更新時(shí)間:2019年02月11日 14:22:16   作者:邋遢的流浪劍客  
今天小編就為大家分享一篇關(guān)于JVM:早期(編譯期)優(yōu)化的深入理解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧

早期(編譯期)優(yōu)化

JVM的編譯器可以分為三個(gè)編譯器:

  1. 前端編譯器:把*.java轉(zhuǎn)變?yōu)?.class的過程。如Sun的Javac、Eclipse JDT中的增量式編譯器(ECJ)
  2. JIT編譯器:把字節(jié)碼轉(zhuǎn)變?yōu)闄C(jī)器碼的過程,如HotSpot VM的C1、C2編譯器
  3. AOT編譯器:靜態(tài)提前編譯器,直接將*.java文件編譯本地機(jī)器代碼的過程

本章的后續(xù)文字里,“編譯期”和“編譯器”都僅限于第一類編譯過程

1、Javac編譯器

Javac編譯器本身就是一個(gè)由Java語言編寫的程序

1)、Javac的源碼與調(diào)試

Javac的源碼存放在JDK_SRC_HOME/langtools/src/share/slasses/com/sun/tools/javac中

編譯過程大致可以分為3個(gè)過程:

  • 解析與填充符號(hào)表過程
  • 插入式注解處理器的注解處理過程
  • 分析與字節(jié)碼生成過程

這3個(gè)步驟之間的關(guān)系與交互順序如下:

2)、解析與符號(hào)填充表

解析步驟由parseFiles()方法完成,解析步驟包括了詞法分析和語法分析兩個(gè)過程

A.詞法分析與語法分析

詞法分析:將源代碼的字符流轉(zhuǎn)變?yōu)闃?biāo)記(Token)集合,單個(gè)字符是程序編寫過程的最小元素,而標(biāo)記則是編譯過程的最小元素,關(guān)鍵字、變量名、字面量、運(yùn)算符都可以成為標(biāo)記,在Javac的源碼中,詞法分析過程由com.sun.tools.javac.parser.Scanner類來實(shí)現(xiàn)。

語法分析是根據(jù)Token序列構(gòu)造抽象語法樹的過程,抽象語法樹是一種用來描述程序代碼語法結(jié)構(gòu)的樹形表述方式。語法樹的每一個(gè)節(jié)點(diǎn)都代表著程序代碼中的一個(gè)語法結(jié)構(gòu),例如包、類型、修飾符、接口、返回值甚至代碼注釋都可以是一個(gè)語法結(jié)構(gòu)。語法分析過程由com.sun.tools.javac.parser.Parser類實(shí)現(xiàn),這個(gè)階段產(chǎn)出的抽象語法樹由com.sun.tools.javac.tree.JCTree類表示,經(jīng)過這個(gè)步驟之后,編譯器就基本不會(huì)再對(duì)源碼文件進(jìn)行操作了,后續(xù)的操作都是建立在抽象語法樹之上的

B.填充符號(hào)表

完成抽象語法樹之后,下一步就是填充符號(hào)表的過程,即enterTrees()方法。符號(hào)表是由一組符號(hào)地址和符號(hào)信息構(gòu)成的表格,類似于哈希表中K-V值對(duì)的形式。符號(hào)表中所登記的信息在編譯的不同階段都要用到。當(dāng)對(duì)符號(hào)名進(jìn)行地址分配時(shí),符號(hào)表是地址分配的依據(jù)。填充過程由com.sun.tools.javac.comp.Enter類實(shí)現(xiàn)

3)、注解處理器

JDK1.5之后,Java提供了對(duì)注解的支持,這些注解與普通的Java代碼一樣,在運(yùn)行期間發(fā)揮作用。 有了編譯器注解處理的標(biāo)準(zhǔn)API后,我們的代碼才有可能干涉編譯器的行為,由于語法樹中的任意元素,甚至包括代碼注釋都可以在插件之中訪問到,所以使用插入式注解處理器在功能上有很大的發(fā)揮空間

4)、語義分析與字節(jié)碼生成

語義分析的主要任務(wù)是對(duì)結(jié)構(gòu)上正確的源程序進(jìn)行上下文有關(guān)性質(zhì)的審查,如進(jìn)行類型審查

A.標(biāo)注檢查

Javac的編譯過程中,語義分析過程分為標(biāo)注檢查以及數(shù)據(jù)及控制流分析兩個(gè)步驟,分別是attribute()flow()方法

標(biāo)準(zhǔn)檢查步驟檢查的內(nèi)容包括諸如變量使用前是否已被聲明、變量與賦值之間的數(shù)據(jù)類型是否能夠匹配等。在標(biāo)準(zhǔn)檢查步驟中,還有一個(gè)重要的動(dòng)作稱為常量折疊

int a = 1 + 2;

語法樹上仍然能看到字面量“1”、“2”以及操作符“+”,但是在經(jīng)過常量折疊以后,它們將會(huì)被折疊為字面量“3”。由于編譯期間進(jìn)行了常量折疊,所以在代碼里面定義“a=1+2”比起直接定義“a=3”,并不會(huì)增加程序運(yùn)行期哪怕僅僅一個(gè)CPU指令的運(yùn)算量

標(biāo)注檢查步驟在Javac源碼中的實(shí)現(xiàn)類是com.xun.tools.javac.comp.Attr和com.sun.tools.javac.comp.Check類

B.數(shù)據(jù)及控制流分析

數(shù)據(jù)及控制流分析可以檢查出諸如程序局部變量在使用前是否有賦值、方法的每條路徑是否都有返回值、是否所有的受查異常都被正確處理了等問題

局部變量與字段(實(shí)例變量、類變量)是有區(qū)別的,它在常量池中沒有CONSTANT_Fielddref_info的符號(hào)引用,自然就沒有訪問標(biāo)志的信息,因此,將局部變量聲明為final,對(duì)運(yùn)行期是沒有影響的,變量的不變性僅僅由編譯器在編譯期間保障。在Javac的源碼中,數(shù)據(jù)及控制流分析的入口是flow()方法,具體操作由com.sun.tools.javac.comp.Flow類來完成

C.解語法糖

語法糖是指在計(jì)算機(jī)語言中添加某種語法,這種語法對(duì)語言的功能并沒有影響,但是更方便程序員使用
Java是一種“低糖語言”,常用的語法糖主要是之前提到的泛型、變長(zhǎng)參數(shù)、自動(dòng)裝箱/拆箱等。虛擬機(jī)運(yùn)行時(shí)不支持這些語法,它們?cè)诰幾g期還原回簡(jiǎn)單的基礎(chǔ)語法結(jié)構(gòu),這個(gè)過程稱為解語法糖。解語法糖的過程是由desuger()方法觸發(fā)的

D.字節(jié)碼生成

字節(jié)碼生成是Javac編譯過程的最后一個(gè)階段,由com.sun.tools.javac.jvm,Gen類來完成,字節(jié)碼生成階段不僅僅是把前面各個(gè)步驟所生成的信息(語法樹、符號(hào)表)轉(zhuǎn)化為字節(jié)碼寫入磁盤中,編譯器還進(jìn)行了少量代碼添加和轉(zhuǎn)換工作

實(shí)例構(gòu)造器<init>()方法和類構(gòu)造器<client>()方法就是在這個(gè)階段添加到語法樹之中的,這兩個(gè)構(gòu)造器的產(chǎn)生過程實(shí)際上是一個(gè)代碼收斂的過程,編譯器會(huì)把語句塊(對(duì)于實(shí)例構(gòu)造器而言是{}塊,對(duì)于類構(gòu)造器而言是static{}塊)、變量初始化(實(shí)例變量和類變量)、調(diào)用父類的實(shí)例構(gòu)造器等操作收斂到<init>()<client>()方法之中,并且保證一定是按先執(zhí)行父類的實(shí)例構(gòu)造器,然后初始化變量,最后執(zhí)行語句塊的順序進(jìn)行,上面所述的動(dòng)態(tài)由Gen.normalizeDefs()方法來實(shí)現(xiàn)

完成對(duì)語法樹的遍歷與調(diào)整之后,就會(huì)把填充了所有所需信息的符號(hào)表交給com.sun.tools.javac.jvm.ClassWriter類,由這個(gè)類的wrtieClass()方法輸出字節(jié)碼,生成最終的Class文件

2、Java語法糖的味道

1)、泛型與類型擦除

泛型是JDK1.5的一項(xiàng)新增特性,它的本質(zhì)是參數(shù)化類型的應(yīng)用,也就是說所操作的數(shù)據(jù)類型被指定為一個(gè)參數(shù)。這種參數(shù)類型可以用在類、接口和方法的創(chuàng)建中,分別稱為泛型類、泛型接口和泛型方法

Java語言中的泛型則不一樣,它只在程序源碼中存在,在編譯后的字節(jié)碼文件中,就已經(jīng)替換為原來的原生類型了,并且在相應(yīng)的地方插入了強(qiáng)制轉(zhuǎn)型代碼,因此,對(duì)于運(yùn)行期的Java語言來說,ArrayList<int>ArrayList<String>就是同一個(gè)類,所以泛型技術(shù)實(shí)際上是Java語言的一顆語法糖,Java語言中的泛型實(shí)現(xiàn)方法稱為類型擦除,基于這種方法實(shí)現(xiàn)的泛型稱為偽泛型

 public static void main(String[] args) {
 Map<String, String> map = new HashMap<String, String>();
 map.put("hello", "你好");
 map.put("how are you?", "吃了沒?");
 System.out.println(map.get("hello"));
 System.out.println(map.get("how are you?"));
 }

把這段Java代碼編譯成Class文件,然后再用字節(jié)碼反編譯工具進(jìn)行反編譯后,代碼如下:

 public static void main(String[] paramArrayOfString)
 {
  HashMap localHashMap = new HashMap();
  localHashMap.put("hello", "你好");
  localHashMap.put("how are you?", "吃了沒?");
  System.out.println((String)localHashMap.get("hello"));
  System.out.println((String)localHashMap.get("how are you?"));
 }

當(dāng)泛型遇到重載:

 public static String method(List<String> list) {
 System.out.println("invoke method(List<String> list)");
 }
 public static int method(List<Integer> list) {
 System.out.println("invoke method(List<Integer> list)");
 }

這段代碼是不能被編譯的,因此參數(shù)List<String>List<Integer>編譯之后都被擦除了,變成了一樣的原生類型List<E>,擦除動(dòng)作導(dǎo)致這兩種方法的特征簽名變得一模一樣

2)、自動(dòng)裝箱、拆箱與遍歷循環(huán)

自動(dòng)裝箱、拆箱在編譯之后被轉(zhuǎn)化成了對(duì)應(yīng)的包裝和還原方法,遍歷循環(huán)則把代碼還原成了迭代器的實(shí)現(xiàn),這也是為何遍歷循環(huán)需要被遍歷的類實(shí)現(xiàn)Iterable接口的原因,變長(zhǎng)參數(shù)在調(diào)用的時(shí)候變成了一個(gè)數(shù)組類型的參數(shù)

 public static void main(String[] args) {
 Integer a = 1;
 Integer b = 2;
 Integer c = 3;
 Integer d = 3;
 Integer e = 321;
 Integer f = 321;
 Long g = 3L;
 System.out.println(c == d);// true
 System.out.println(e == f);// false
 System.out.println(c == (a + b));// true
 System.out.println(c.equals(a + b));// true
 System.out.println(g == (a + b));// true
 System.out.println(g.equals(a + b));// false
 }

包裝類的“==”運(yùn)算在不遇到算術(shù)運(yùn)算的情況下不會(huì)自動(dòng)拆箱,以及它們equals()方法不處理數(shù)據(jù)轉(zhuǎn)型的關(guān)系

3)、條件編譯

Java語言使用條件為常量的if語句,此代碼中的if語句不同于其他Java代碼,它在編譯階段就會(huì)被運(yùn)行,生成的字節(jié)碼之中只包含條件正確的部分

 public static void main(String[] args) {
 if (true) {
  System.out.println("block 1");
 } else {
  System.out.println("block 2");
 }
 }

Java語言中條件編譯的實(shí)現(xiàn),也是Java語言的一顆語法糖,根據(jù)布爾常量值的真假,編譯器將會(huì)把分支中不成立的代碼塊消除掉,這是在解語法糖階段實(shí)現(xiàn)的

Java語言中還有不少的其他語言糖,如內(nèi)部類、枚舉類、斷言語句、對(duì)枚舉和字符串的switch支持、try語句中定義和關(guān)閉資源等等

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接

相關(guān)文章

  • java下載url路徑包含中文需要轉(zhuǎn)義的操作

    java下載url路徑包含中文需要轉(zhuǎn)義的操作

    這篇文章主要介紹了java下載url路徑包含中文需要轉(zhuǎn)義的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • spring 整合 mybatis 中數(shù)據(jù)源的幾種配置方式(總結(jié)篇)

    spring 整合 mybatis 中數(shù)據(jù)源的幾種配置方式(總結(jié)篇)

    因?yàn)閟pring 整合mybatis的過程中, 有好幾種整合方式,尤其是數(shù)據(jù)源那塊,經(jīng)常看到不一樣的配置方式,總感覺有點(diǎn)亂,所以今天有空總結(jié)下,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧
    2018-05-05
  • 一文帶你掌握SpringBoot中常見定時(shí)任務(wù)的實(shí)現(xiàn)

    一文帶你掌握SpringBoot中常見定時(shí)任務(wù)的實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了Spring?Boot中定時(shí)任務(wù)的基本用法、高級(jí)特性以及最佳實(shí)踐,幫助開發(fā)人員更好地理解和應(yīng)用定時(shí)任務(wù),提高系統(tǒng)的穩(wěn)定性和可靠性,需要的可以參考下
    2024-03-03
  • 詳解Java中的sleep()和wait()的區(qū)別

    詳解Java中的sleep()和wait()的區(qū)別

    這篇文章主要介紹了詳解Java中的sleep()和wait()的區(qū)別的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • Java?API文檔的使用方法詳解

    Java?API文檔的使用方法詳解

    在開發(fā)過程中如果遇到疑難問題,除了可以在網(wǎng)絡(luò)中尋找答案,也可以在Java API幫助文檔(簡(jiǎn)稱"JDK文檔"”)中查找答案,下面這篇文章主要給大家介紹了關(guān)于Java?API文檔使用的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • Java仿文庫的基本方法(openoffice+swftools+flexPaper)

    Java仿文庫的基本方法(openoffice+swftools+flexPaper)

    這篇文章主要為大家詳細(xì)介紹了Java仿文庫的基本方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • 玩轉(zhuǎn)spring boot 快速開始(1)

    玩轉(zhuǎn)spring boot 快速開始(1)

    玩轉(zhuǎn)spring boot,快速開始spring boot學(xué)習(xí),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • springboot項(xiàng)目如何設(shè)置時(shí)區(qū)

    springboot項(xiàng)目如何設(shè)置時(shí)區(qū)

    這篇文章主要介紹了springboot項(xiàng)目如何設(shè)置時(shí)區(qū)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java日期與時(shí)間類原理解析

    Java日期與時(shí)間類原理解析

    這篇文章主要介紹了Java日期與時(shí)間類原理解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • 詳解elasticsearch實(shí)現(xiàn)基于拼音搜索

    詳解elasticsearch實(shí)現(xiàn)基于拼音搜索

    這篇文章主要為大家介紹了詳解elasticsearch實(shí)現(xiàn)基于拼音搜索示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01

最新評(píng)論

伊宁市| 留坝县| 汝南县| 清苑县| 昭平县| 新干县| 梁山县| 互助| 健康| 台中市| 同江市| 老河口市| 沁源县| 板桥市| 宁德市| 博兴县| 汝州市| 元阳县| 林甸县| 鄢陵县| 广西| 宁陵县| 孝义市| 永胜县| 明光市| 彭山县| 砀山县| 北辰区| 嫩江县| 靖江市| 宜君县| 元谋县| 侯马市| 平原县| 双桥区| 尼勒克县| 莱阳市| 天镇县| 湖北省| 疏勒县| 伊宁县|