精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

奇怪的知識點:用代碼run代碼

開發 前端
文章是由android的知識引入,但真正想聊的東西是編譯原理。所以:才有了標題《奇怪的知識點》。因此各位看官沒必要太糾結自己沒有學過android或者Java,不影響閱讀~

 [[387466]]

本文轉載自微信公眾號「咸魚正翻身」,作者MDove。轉載本文請聯系咸魚正翻身公眾號。 

前言

人閑下來就會對各種各樣的東西感到好奇,好奇的東西多了就發現自己是真的菜。

今天這篇文章寫出來的原因,源自一次非常非常“詭異的”IDE的語法錯誤提示。

文章是由android的知識引入,但真正想聊的東西是編譯原理。所以:才有了標題《奇怪的知識點》。因此各位看官沒必要太糾結自己沒有學過android或者Java,不影響閱讀~

復現一次語法錯誤的代碼:

正文

一、android知識部分

IDE提示的也很明白:res的id不能在library級別的module中的switch語法中應用。原因是res的id不是常量。

注意:同樣的代碼在application級別的module中是沒有語法問題的。所以對于res的id來說,application中是常量,library中不是常量。如果有同學看過R的內容,就會發現的確如此:

這個是application中的R文件:

這個是library中的R文件:

這個顯現引申出一個android打包的知識點:aapt[1]過程中的資源合并[2]。

一句話描述這個知識點:不同module之間的重復的資源會按優先級的進行合并覆蓋。這個流程引發的問題,很多老司機都遇到過,資源被覆蓋了,我們引用的資源永遠會被指向唯一的res。這肯定是不符合預期的。

因此諸如給資源名加前綴的方案便應運而生。

為什么不是final

這里咱們聊一個問題:常量有什么特別之處?下面的代碼,編譯之后就是能看到常量的特別之處:

  1. class TestFinal { 
  2.     static final int sInt = 1; 
  3.  
  4.     void testFinal(){ 
  5.         int temp = sInt; 
  6.         System.out.println(temp); 
  7.     } 

編譯后的代碼會是這樣:

  1. public void testFinal(){ 
  2.     System.out.println(1); 

會發現編譯器的優化,會把常量直接內聯到代碼引用之處。那么咱們想想:如果library里的res也是常量會出現什么問題?

常量被內聯,一旦發生項目中資源重復,打包過程中就出現覆蓋,那么內聯的常量已經不能映射到真正的資源上了,畢竟資源已經被覆蓋。

也就是會出現:資源找不到的crash

不是final引發的問題

library中的R引用不是常量,就意味著這種用法是不能工作的:

可以看到,注解也是要常量的,所以這個問題對我們日常影響還是挺大的...等等!Butterknife就是注解的這種用法,為什么沒有問題??

深入了解過Butterknife的同學應該知道,Butterknife針對這種情況進行了特殊處理:

Butterknife的方案

Butterknife為了不讓注解處出現語法錯誤,自己創造了一個叫做R2的類。這個類其實就是原樣copy了R,唯一不同就是R2都是常量。

的確這樣不會有語法錯誤,但是咱們剛才也分析了:常量內聯,資源覆蓋。所以一旦滿足case,那就是crash。所以Butterknife又是如何規避這個問題的呢?

看過Butterknife中findViewById()源碼的同學應該都知道,此處Butterknife的實現大概是這樣:

  1. public TestActivity_ViewBinding(T target, View source) { 
  2.     this.target = target; 
  3.     target.parentLayout = Utils.findRequiredViewAsType(source, R.id.test, "field 'parentLayout'", ViewGroup.class); 

我們能夠看到,Butterknife最終打進包里的代碼,并沒有發生常量內聯!所以它是怎么做的呢?

看到這里的同學,不妨停下來想想,如果是你會怎么解決這個問題?這里我說說我能想到的方案:

ASM階段,把內聯的代碼,再給它改寫成R的正常引用。問題就來了:ASM的輸入是class,這個時機我沒辦法再拿到R的正常引用了。

那如果繼續提前這個干預的過程,放到APT階段呢?試了一下,也沒有搞定。APT階段拿到的注解value也已經是被內聯的常量了...

這就有點奇怪了,Butterknife是如何做到通過內聯的常量和R引用的映射呢?翻看了Butterknife的源碼,發現Butterknife是在APT階段執行的,關鍵類在ButterKnifeProcessor[3]。

Butterknife通過JCTree這個api拿到了R的引用,然后把內聯的代碼又改回了R的引用。具體的api實現咱們就不看了,有興趣的同學可以自行github。

咱們接下來聊一聊這個JCTree是干啥的?

二、編譯原理

我們都知道:日常我們寫下的代碼,最終想要運行在目標機器上都需要編譯成目標機器能夠識別的機器碼。而做這些工作的我們稱之為編譯器。一般編譯器就是干了如下的事情:

圖片來自《編譯原理》第二版

在各種源碼編譯的實現中,基本都不約而同地抽象出一個概念:抽象語法樹(AST),以求在整個編譯實現過程更加的方便。

一句話解釋抽象語法樹:源代碼語法結構的一種抽象表示。它以樹狀的形式表現編程語言的語法結構,樹上的每個節點都表示源代碼中的一種結構。

咱們粗略了解了編譯器的的實現流程,那么編譯器又是怎么實現的呢?當然是用代碼實現的咯,而且它們的實現往往離我們很近...以我們java編譯器為例。

入坑Java時,我們應該都試過javac。而這個命令的實現在哪?就在JDK里的tools.jar中的com.sun.tools.javac.Main包下。核心邏輯在于com.sun.tools.javac.main.JavaCompiler。

這里邊就實現了如何分析我們的源碼,如何轉化成class。也就上那個圖中編譯器該干的事。

那么JCTree在整個編譯過程中充當什么角色呢?一句話:JCTree是對源碼的一種api級別的描述。或者說JCTree是java編譯流程中語法樹的實現。

也就是說通過JCTree相關api,我們可以訪問到源碼結構。說起來似乎很抽象,我們debug個一段代碼就能get到它存在的意義了:

  1. fun main() { 
  2.     val context = Context() 
  3.     val scanner = RScanner() 
  4.     val javaCompiler = JavaCompiler.instance(context) 
  5.     val testJavaCodeFile = File("/Users/x/xx/xxx/TestAutoCode.java"
  6.  
  7.     ToolProvider 
  8.         .getSystemJavaCompiler() 
  9.         .getStandardFileManager(DiagnosticCollector(), nullnull
  10.         .getJavaFileObjectsFromFiles(listOf(testJavaCodeFile)) 
  11.         .forEach { 
  12.             javaCompiler.parse(it).defs.forEach { 
  13.                 scanner.scan(it) 
  14.             } 
  15.          } 
  16.  
  17. class RScanner : TreeScanner() { 
  18.     override fun visitMethodDef(tree: JCTree.JCMethodDecl?) { 
  19.         super.visitMethodDef(tree) 
  20.     } 

基于這一套api我們是能夠獲取到源碼的任何信息的。而且這段demo代碼,只需要導入tools.jar就可以快速運行,成本非常的低。

三、用代碼run代碼

上述我們通過JavaCompiler的實例,對java源碼進行了動態的編譯,拿到的結果就是這個java源碼的class文件。有了class文件,我們就可以通過ClassLoader去加載這個class。

有了上邊的基礎,實現源碼已經不重要,這里貼一個鏈接大家自取吧:How do you dynamically compile and load external java classes?[4]

尾聲

我個人沒有正經的學過編譯原理,所以了解這部分內容時,覺得還是挺神奇的。也希望這篇文章能對同樣沒有學過編譯原理的同學帶來一些思考和啟發~

References

[1] aapt: https://developer.android.com/studio/command-line/aapt2?hl=zh_cn

[2] 資源合并: https://developer.android.com/studio/write/add-resources?hl=zh-cn#resource_merging

[3] ButterKnifeProcessor: https://github.com/JakeWharton/butterknife/blob/fcdebedf3276096db2f51bf6372b849b5a9c75ed/butterknife-compiler/src/main/java/butterknife/compiler/ButterKnifeProcessor.java#L1470

[4] How do you dynamically compile and load external java classes?: https://stackoverflow.com/questions/21544446/how-do-you-dynamically-compile-and-load-external-java-classes

責任編輯:武曉燕 來源: 咸魚正翻身
相關推薦

2016-05-30 17:31:34

Spring框架

2010-08-17 14:56:00

HCNE認證

2011-04-15 12:25:21

BGP路由

2011-04-01 15:28:40

Zabbix配置安裝

2021-04-13 08:25:12

測試開發Java注解Spring

2010-06-17 16:42:04

UML

2010-07-27 15:49:28

Flex

2009-12-18 17:34:38

Ruby線程

2021-01-18 10:33:53

Java反射模塊

2009-08-06 17:42:32

C#知識點

2025-05-07 08:55:00

2010-08-18 10:52:46

Linux筆試

2025-05-19 10:00:00

MySQL數據庫InnoDB

2020-10-07 15:15:41

Python

2025-07-09 09:05:00

2010-09-02 10:11:11

華為認證

2022-08-01 07:42:17

線程安全場景

2018-11-28 14:30:09

MySQLL索引設計數據庫

2009-08-02 21:47:35

安防線纜

2012-04-23 15:49:04

點贊
收藏

51CTO技術棧公眾號

亚洲福利影院| www.成人精品| 国产精品伦理久久久久久| 欧美人动与zoxxxx乱| 亚洲国产一二三精品无码| 日韩一级片免费看| 午夜av一区| 亚洲成人av片在线观看| 丰满少妇在线观看| 污视频网站免费在线观看| 99久久777色| 国产精品亚洲综合天堂夜夜| 国产精品久久久久久久无码| 精品免费av在线| 亚洲精品乱码久久久久久| 精品亚洲欧美日韩| 国产又粗又猛又黄| 国产综合网站| 精品国产免费一区二区三区香蕉| 亚洲第一综合网站| 欧洲天堂在线观看| 国产成人在线电影| 国产精品视频公开费视频| 精品在线视频免费观看| 成人3d动漫在线观看| 亚洲国产精品va在看黑人| 99九九精品视频| 日本肉肉一区| 色婷婷亚洲婷婷| 久青草视频在线播放| 中文字幕在线播放| 国产精品一区二区在线观看不卡| 欧美极品少妇xxxxx| 黄色av片三级三级三级免费看| 亚洲日本免费电影| 色激情天天射综合网| 水蜜桃一区二区三区| 日韩一级免费毛片| 国产电影一区二区三区| 97久久国产精品| 超碰手机在线观看| 久久久影院免费| 国产亚洲xxx| 亚洲欧美自拍另类日韩| 黄色网页在线看| 国产精品乱子久久久久| 国产福利一区二区三区在线观看| 奇米影视第四色777| 好看不卡的中文字幕| 欧美成人精品在线播放| h色网站在线观看| 999久久久亚洲| 自拍偷拍亚洲精品| 337人体粉嫩噜噜噜| 激情五月综合| 中文字幕久热精品视频在线| 亚洲成人黄色av| 成人动漫免费在线观看| 一本大道久久加勒比香蕉| 乐播av一区二区三区| 国产日产一区| 这里只有精品视频| 波多野结衣喷潮| 91精品推荐| 欧美日本在线视频中文字字幕| 九色porny自拍视频| 国产探花在线精品一区二区| 亚洲丝袜在线视频| 国产在线观看免费播放| 91成人噜噜噜在线播放| 亚洲精品一区二区在线观看| 日韩成人av一区二区| 亚洲婷婷影院| 在线日韩av观看| 免费成人深夜蜜桃视频| 天天射天天综合网| 九九热精品视频国产| 国产视频123区| 中文字幕一区二区三三| 中文字幕精品久久| www深夜成人a√在线| 欧美色女视频| 欧美成人激情视频| 国产午夜久久久| 久久精品一区| 91探花福利精品国产自产在线| 艳妇乳肉豪妇荡乳av无码福利| 国产欧美三级| 国产精品三级网站| 超碰在线观看99| 久久视频一区二区| 中文字幕中文字幕在线中一区高清| 欧美偷拍视频| 91视视频在线直接观看在线看网页在线看| 3d精品h动漫啪啪一区二区| 国产 日韩 欧美 精品| 久久久久久久综合日本| 超碰在线免费观看97| 18免费在线视频| 亚洲已满18点击进入久久| 久久久久久久久影视| 自由日本语热亚洲人| 欧美精选在线播放| 一起草在线视频| 图片区亚洲欧美小说区| 久久电影一区二区| 亚洲影院在线播放| 国产乱码一区二区三区| 区一区二区三区中文字幕| 97超碰资源站在线观看| 一区二区三区美女| 亚洲成色www.777999| 荡女精品导航| 久久精品中文字幕| av片免费观看| av在线这里只有精品| 自拍偷拍一区二区三区| 污片在线免费观看| 欧美日本乱大交xxxxx| 国产国语性生话播放| 亚洲欧美一区在线| 国产日韩欧美综合| www.五月天激情| 国产精品嫩草99a| 国产一二三四区在线观看| 黄页网站在线观看免费| 欧美日产国产精品| 免费看黄色的视频| 亚洲欧美久久久| 国产日韩在线免费| 国产在线视频网址| 五月天精品一区二区三区| 国产又粗又长又大的视频| 日韩手机在线| 午夜精品福利在线观看| 亚洲免费不卡视频| 亚洲激情自拍偷拍| 亚洲国产日韩在线一区| 欧美性生活一级片| 日韩小视频在线| 国产亚洲成人精品| 国产精品一区二区三区网站| 欧美 另类 交| 高清一区二区三区av| 亚洲国产成人在线视频| 久久久久亚洲天堂| 国产成人免费视频| a级黄色片免费| 免费观看亚洲视频大全| 麻豆国产精品va在线观看不卡| 国内精品福利视频| 91丨九色丨国产丨porny| 日韩视频在线免费播放| 91久久青草| 免费97视频在线精品国自产拍| 男人日女人网站| 久久综合狠狠综合久久综合88 | 久久久精品电影| 黄网在线观看视频| 91麻豆精东视频| 欧美日韩中文字幕在线播放| 欧美国产中文高清| 国内免费久久久久久久久久久| 91丨porny丨在线中文| 中文字幕一区日韩精品欧美| www.爱色av.com| 免费视频国产一区| 国产日韩欧美视频在线| 在线欧美三级| 欧美美女福利视频| 精品国产乱码久久久久久图片| 制服 丝袜 综合 日韩 欧美| 天堂在线一区二区| 亚洲一区二区三区色| 国产亚洲字幕| 日韩在线不卡视频| 五月婷婷激情视频| 成人精品高清在线| 欧美黄网在线观看| 国产一区二区高清在线| 久久久久久久一区二区三区| 无套内谢的新婚少妇国语播放| 一二三四区精品视频| 看全色黄大色黄女片18| 日韩中文字幕区一区有砖一区| 狠狠色综合色区| 色豆豆成人网| 久久不射电影网| 99国产精品久久久久99打野战| 国产精品情趣视频| 欧美做受高潮中文字幕| 日韩不卡一区二区三区| 一本色道久久综合亚洲二区三区 | 性做久久久久久久久| av在线网站观看| 一本久道久久综合婷婷鲸鱼| 日韩欧美在线电影| 亚洲电影一区| 国产成人精品免高潮在线观看| 欧美美乳在线| 9191久久久久久久久久久| 国产精品成人久久| 国产精品美女久久久久aⅴ国产馆| 成年人小视频网站| 一区二区三区四区在线观看国产日韩| 国产日韩精品在线| 人人草在线视频| 亚洲精品一区二区三区婷婷月| 国产又大又黑又粗免费视频| 成人国产视频在线观看| 人人妻人人澡人人爽欧美一区| 亚洲国产欧美在线观看| 日本中文字幕成人| 青青在线视频| 日韩精品在线播放| 亚洲欧美偷拍一区| 亚洲精品成人悠悠色影视| 亚洲成人网在线播放| 国产精品资源在线看| 99热手机在线| 亚洲欧美久久久| 被灌满精子的波多野结衣| 久久一级电影| 欧美重口乱码一区二区| 国模一区二区| 2019最新中文字幕| 婷婷丁香在线| 日韩亚洲综合在线| 国产鲁鲁视频在线观看免费| 欧美日本一区二区| 欧美超碰在线观看| 精品人伦一区二区三区蜜桃网站| 国产黄色三级网站| 日本女优在线视频一区二区| 在线观看日韩羞羞视频| 欧美日韩高清| 欧美在线视频二区| 九九热精品视频在线观看| 精品综合久久久| 青草久久视频| 精品网站在线看| 国产成人在线中文字幕| 日韩美女视频免费看| 美女露胸视频在线观看| 91sa在线看| 国产精品vvv| 97在线观看免费高清| 欧美aaaaaaa| 久久久久久com| 变态调教一区二区三区| 欧美极品少妇与黑人| 国产精品国精产品一二| 欧美人与性动交a欧美精品| 欧美人与性动交α欧美精品济南到| 亚洲区免费影片| 蜜桃视频在线播放| 亚洲人成免费电影| freemovies性欧美| 色婷婷综合成人av| 亚洲欧美色视频| 亚洲免费精彩视频| 精品人妻伦一二三区久久| 日韩欧美在线网站| 精品欧美一区二区精品少妇| 亚洲精品一区二区三区影院| 中文字幕一区2区3区| 欧美女孩性生活视频| 国产高清视频免费观看| 日韩欧美电影一区| 人妻无码中文字幕| 日韩亚洲欧美在线| 人人妻人人澡人人爽久久av| 亚洲精品美女免费| 久久久资源网| 精品国产拍在线观看| 久久国产精品黑丝| 欧洲精品久久久| 国产69精品久久久久按摩| 亚洲在线视频观看| 久9re热视频这里只有精品| 欧美另类一区| 雨宫琴音一区二区三区| 拔插拔插海外华人免费| 日韩高清不卡在线| 成人中文字幕在线播放| 日本麻豆一区二区三区视频| 免费成人在线视频网站| 美女在线观看视频一区二区| 国产v亚洲v天堂无码久久久| 麻豆91在线播放免费| 自拍视频第一页| 久久亚洲免费视频| 日韩福利小视频| 精品国产1区2区| 伊人精品一区二区三区| 欧美变态凌虐bdsm| 久久久久久久影视| 亚洲深夜福利视频| 91黄色在线| 国产97免费视| 综合激情久久| 日韩精品资源| 波多野结衣的一区二区三区| 青青青在线观看视频| 禁久久精品乱码| 国产视频手机在线播放| 懂色av一区二区三区免费观看| 中国特级黄色大片| 国产精品久久久久久久久果冻传媒 | 亚洲精品美女在线| 日本最黄一级片免费在线| 久久久久久久电影一区| 国产精品伦一区二区| 精品欧美一区二区在线观看视频 | 蜜桃视频m3u8在线观看| 91精品国产成人| 疯狂欧洲av久久成人av电影| 欧美日韩综合精品| 欧美午夜国产| 免费网站在线观看黄| 国产精品99久久久久久久vr| 成人激情五月天| 欧美日韩中文字幕| 中文在线免费看视频| 亚洲精品美女久久久| 国产网站在线播放| 97精品视频在线观看| 精品亚洲美女网站| 久久亚洲精品欧美| 亚洲国内自拍| 亚洲免费在线播放视频| 国产精品系列在线| 欧美成人一区二区三区四区| 亚洲国产婷婷香蕉久久久久久| 青青草视频免费在线观看| 欧美精品成人在线| 一区二区三区在线免费看| 中文字幕欧美日韩一区二区三区| 午夜精品影院| www.污污视频| 国产精品二区一区二区aⅴ污介绍| 2018天天弄| 日韩一区二区免费在线电影| 国精产品一区| 亚洲一区二区三区毛片| 99久久婷婷这里只有精品| 久久99爱视频| 成人免费小视频| 国产一区二区三区黄片| 日韩中文字幕网站| 亚洲精品大片| 熟女视频一区二区三区| 韩国三级在线一区| 91中文字幕永久在线| 欧美视频免费在线观看| 日韩福利一区二区| 日产日韩在线亚洲欧美| 国产精品美女久久久久久不卡| 成人av在线播放观看| 国产成人啪免费观看软件| 国产毛片欧美毛片久久久| 在线一区二区三区做爰视频网站| 国产又黄又粗又长| 亚洲午夜未满十八勿入免费观看全集 | 国产91欧美| 男插女免费视频| 国产精品一二三区| 69精品久久久| 亚洲人成五月天| 日韩久久一区| 91网站在线观看免费| 99久久婷婷国产综合精品电影| 嘿嘿视频在线观看| 欧美一区二区视频观看视频| 欧美伦理免费在线| 玖玖玖精品中文字幕| 日韩经典一区二区| 亚洲欧洲综合网| 精品人在线二区三区| 性欧美又大又长又硬| 日韩高清dvd| 国产一级精品在线| 久久午夜免费视频| 中日韩美女免费视频网站在线观看| japanese色国产在线看视频| 女同一区二区| 久久99热国产| 日韩成人一区二区三区| 伊人久久综合97精品| 久久精品免视看国产成人| 国产美女主播在线播放| 国产精品视频一区二区三区不卡| 日韩电影在线观看一区二区| zzijzzij亚洲日本成熟少妇| 91亚洲精品视频在线观看| 亚洲激情在线观看视频| 一区av在线播放| 丁香婷婷在线观看| 国产精品一区二区三区四区五区| 国自产拍偷拍福利精品免费一|