最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(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ó)家法律
通榆县| 方正县| 宁国市| 会泽县| 富顺县| 嘉定区| 南乐县| 洛浦县| 神木县| 札达县| 淮阳县| 庐江县| 涟水县| 佛学| 仙桃市| 广水市| 安宁市| 肃南| 余干县| 开阳县| 平乡县| 富裕县| 瓦房店市| 保康县| 年辖:市辖区| 长乐市| 呼伦贝尔市| 绥江县| 长武县| 苗栗市| 平罗县| 渭源县| 洱源县| 遵义县| 武川县| 治多县| 美姑县| 临武县| 宣恩县| 平昌县| 政和县|