无码av一区二区三区无码,在线观看老湿视频福利,日韩经典三级片,成 人色 网 站 欧美大片在线观看

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Java ASM詳解:模塊

2022-10-18 00:53 作者:Nickid2018  | 我要投稿

在前兩篇專欄中我們討論了各種類的結(jié)構(gòu),將各種類組織一起它們就組成了模塊(Module)。

模塊的定義

模塊是在 Java 9 中引入的,它在module-info.java文件中定義。這個(gè)文件的內(nèi)容是一個(gè)模塊的描述,下面就是一個(gè)例子:

上面的代碼聲明了一個(gè)模塊,名稱為 JavaASMTest,并依賴模塊 org.objectweb.asm。

在模塊中,我們可以定義以下信息:

  1. requires 語句,它代表了這個(gè)模塊需要依賴于什么其它的模塊。所有的模塊都隱式定義了requires java.base。
    requires 語句可以使用 static 修飾符,代表靜態(tài)依賴。這種依賴在編譯期是必須的,但是在運(yùn)行時(shí)可以不存在。
    requires 語句也可以使用 transitive 修飾符,它代表了依賴此模塊的模塊將隱式獲得對(duì)本模塊依賴的模塊的可讀性。舉一個(gè)例子:如果 A 依賴于 B,B 依賴于 C,那么 C 對(duì) A 來說不可讀,除非 A 顯式定義 requires C;但是加上這個(gè)關(guān)鍵詞,C 將對(duì) A 可讀。

  2. exports 語句,它代表了模塊內(nèi)某個(gè)包內(nèi)的 public 成員可以被其他模塊訪問,也就是開放了可讀性。如果一個(gè)模塊代碼中直接訪問了一個(gè)其他模塊沒有 exports 的成員,那么代碼不通過編譯。 exports 語句可以和 to 搭配,代表對(duì)指定模塊開放這些成員。

  3. opens 語句,和 exports 類似,但是它開放的是訪問性。也就是說,允許通過反射訪問模塊中的類。這個(gè)語句也可以和 to 搭配。 當(dāng)模塊被定義為 open module 時(shí),模塊內(nèi)的所有成員都將開放訪問,并且不允許在模塊中重新定義 opens。

  4. uses 語句,用于使用服務(wù)。服務(wù)通常是抽象類,比如說 java.sql.Driver。服務(wù)類所在的模塊必須使用 requires 進(jìn)行依賴。

  5. provides ... with ... 語句,它代表提供服務(wù)的實(shí)現(xiàn)類。

下面是 opens 和 exports 搭配使用的情況:

opens 和 exports 搭配使用的情況

模塊的字節(jié)碼表示

和普通的類一樣,模塊也是使用 ClassWriter 寫入的,但是寫入類信息的時(shí)候和普通的類不一樣:它要求類名稱是 module-info,僅帶有 ACC_MODULE 訪問標(biāo)志,并且沒有超類和簽名

接下來就是寫入模塊信息,這里用到了 visitModule 方法。如果模塊是 open 的,那么訪問標(biāo)志要寫為 ACC_OPEN,否則寫為0。最后一個(gè)參數(shù)是模塊的版本,可以為 null。

模塊中有三種定義信息的模式:

  • 顯式定義,也就是在文件中顯式寫出

  • 隱式定義,由模塊的依賴關(guān)系自行推斷而出

  • 既不是顯式定義也不是隱式定義,由編譯器編譯時(shí)決定添加

如果訪問標(biāo)志含有 ACC_MANDATED,則說明這個(gè)信息是被隱式定義的;如果訪問標(biāo)志含有 ACC_SYNTHETIC,則這個(gè)模塊信息既不是顯式定義也不是隱式定義。所有使用訪問標(biāo)志的模塊信息都可以使用這兩個(gè)標(biāo)志,下文將不再重復(fù)出現(xiàn)。

接下來就是填充模塊的信息,這些信息與 ModuleVisitor 類中的方法一一對(duì)應(yīng)。

requires 語句對(duì)應(yīng) visitRequire 方法,第一個(gè)參數(shù)是依賴模塊的名稱,最后一個(gè)參數(shù)是依賴模塊的版本。第二個(gè)參數(shù)訪問標(biāo)志可以使用 ACC_TRANSITIVE ACC_STATIC_PHASE,分別代表了 transitive static。

由于所有的模塊都隱式定義了 requires java.base,所以所有模塊都必須像下面一樣寫入:

exports opens 語句分別使用了 visitExport visitOpen 方法,參數(shù)分別是全限定包名、訪問標(biāo)志和指定模塊列表,最后一個(gè)參數(shù)可以為 null,代表向所有模塊開放。

uses 語句使用 visitUse 方法寫入,它唯一的參數(shù)代表服務(wù)類全限定名。

provides ... with ... 語句使用 visitProvide 方法,其中第一個(gè)參數(shù)代表服務(wù)類的全限定名,第二個(gè)則是實(shí)現(xiàn)類的列表。

現(xiàn)在,ModuleVisitor 類中還有兩個(gè)方法我們沒有說到:visitPackage visitMainClass。這兩個(gè)方法的實(shí)際作用不大,所以不講解它的用法。

到這里模塊的知識(shí)就結(jié)束了,下一篇專欄將講述注解的使用。

若無特殊說明,所有字節(jié)碼均以 Java 17 為標(biāo)準(zhǔn)。

參考資料:

  • The Java Language Specification (Java SE 17 Edition)

    https://docs.oracle.com/javase/specs/jls/se17/html/index.html

  • The Java Virtual Machine Specification (Java SE 17 Edition)

    https://docs.oracle.com/javase/specs/jvms/se17/html/index.html

  • ASM 9.4 Javadoc

    https://asm.ow2.io/javadoc/index.html

如果對(duì)文章內(nèi)容有問題或文章有錯(cuò)誤可以評(píng)論區(qū)或私信指出。

Java ASM詳解:模塊的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
柳河县| 涟水县| 宣城市| 巍山| 巴林右旗| 独山县| 台东市| 肃宁县| 文安县| 克拉玛依市| 海南省| 灵宝市| 沙湾县| 寿光市| 广宁县| 滨海县| 竹溪县| 静海县| 炎陵县| 宝鸡市| 资阳市| 谷城县| 岑巩县| 镇巴县| 梅河口市| 临沭县| 台北市| 九台市| 蒙自县| 开封县| 馆陶县| 达州市| 古交市| 黔西县| 华坪县| 天峻县| 浦县| 延川县| 东城区| 广宗县| 德江县|