天天看點

bytebuddy的開發指南-翻譯入門架構概覽編碼約定貢獻路線圖

bytebuddy的開發指南-翻譯

  • 入門
  • 架構概覽
  • 編碼約定
  • 貢獻
  • 路線圖
    • 類型推斷

原文連結

翻譯這個的目的是,簡述了源碼的結構

入門

首先,您需要在本地計算機上建立Byte Buddy的副本。克隆存儲庫後,您可以使用Maven建構項目 。你的shell指令,這可能看起來像這樣:

git clone https://github.com/raphw/byte-buddy.git
cd byte-buddy
mvn package
           

在開始編碼之前,請確定所有測試用例都能成功運作。Byte Buddy的master分支一直都是這種情況。我們目前的Travis版本可以肯定地證明了這一點 ,該版本在監測Byte Buddy的最新狀态。Travis被設定為針對Open JDK

v6

v7

以及 Oracle JDK

v6

v7

來編譯和測試項目 。由于我們某些測試是建立和加載Java類,是以要確定所生成類的格式能被特定Java版本能夠解析。如果您要對Byte Buddy進行更改并且會直接影響所生成的位元組碼,請在送出更改之前確定使用不同的Java版本充分測試您的更改。這些都意味着您需要編寫與Java 6編譯器相容的Java代碼。通常,您的代碼應至少具有90%的測試覆寫率,但是與隻嘗試碰到任何行的測試相比,我們推薦進行徹底(100%)的測試。您可以随時運作Maven的

cobertura:cobertura

來擷取覆寫率。Byte Buddy目前的測試覆寫率是

85%

。作為更現代的替代方法,Byte Buddy還支援通過從Maven 運作變異測試

org.pitest:pitest-maven:mutationCoverage

。但是請記住,與計算覆寫率相比,運作變異測試需要大量額外的運作時間。最後,可以激活Maven 的

integration profile

配置檔案,以掃描代碼庫中潛在的錯誤。這個配置檔案是始終在持續內建伺服器上激活的。 另一方面,

checks profile

聚集了運作速度更快的代碼檢查,并且對于任何Maven建構預設情況下都被激活。

該項目分為不同的子產品。

  • 根項目

    byte-buddy-parent

    是任何Byte Buddy子產品配置的共同基礎。
  • 項目的實作代碼在

    byte-buddy-dev

    子產品。該子產品是直接依賴ASM庫,是以

    dev

    作為子產品的名字。
  • 由于ASM庫·不能保證向後相容性·,是以

    byte-buddy

    子產品負責将ASM依賴關系重新打包到Byte Buddy自己的名稱空間中。這樣做會将ASM依賴(shift)重命名為

    net.bytebuddy.jar.asm

    。這個

    dependency-free

    無依賴的子產品沒有定義其自身的來源,而是依賴于

    byte-buddy-dev

    子產品。在其建構過程中,将解決所有依賴性并建立

    dependency-free

    部署描述符。更多的說明在如何定義對Byte Buddy的依賴關系的部分。為了重新打包,您需要使用

    extras profile

    配置檔案運作Maven建構,這将進一步觸發源代碼的建構和

    javadoc

    的生成。如果

    gpg

    Maven嘗試為所有産出簽名。為了實作這一點, 簽名者必須正确配置

    gpg

    插件。
  • 作為另一個子產品,

    byte-buddy-benchmark

    包含一個 JMH基準測試,,用于測量Byte Buddy的運作時的耗時與性能,來和與其他代碼生成庫相比。
  • byte-buddy-agent

    該子產品提供了一個Java代理,該代理可以增強Byte Buddy的通用API。
  • byte-buddy-android

    子產品包含一個在Android平台上起作用的

    ClassLoadingStrategy

    ,其中

    byte-buddy-android-test

    子產品定義了一個應用此政策的測試應用程式。這僅當

    android profile

    配置檔案被激活時才建構它,因為構模組化塊需要Android SDK。

架構概覽

每個代碼生成架構都需要一種反映類型及其成員的方法。Byte Buddy通過

TypeDescription

接口通路類型資訊。該接口提供的API 和Java反射API 中定義的

Class

相似,并且可以使用

TypeDescription.ForLoadedType

來代表加載過的類,這個會包括具體的類型。但是,Byte Buddy也可以用于建立

Java agent

,在該Java agent中,需要在加載類之前對類進行操作。是以,Byte Buddy永遠不會對已經加載過的類型進行操作。所有

描述類型接口

都在

net.bytebuddy.description

包中找到。

同樣,Byte Buddy将泛型描述為·

ypeDescription.Generic

接口的執行個體。該接口比Java自身的等效接口(TypeByte Buddy的

Type

接口,提供了用于處理各種通用類型的方法)豐富。當使用泛型的一些不支援的功能時将引發異常。我們選擇這種方法作為Java語言所需的類型轉換方法更簡介的替代。由于大多數操作是由

visitors(asm通路位元組碼的接口)

執行的,是以實際上這并不是問題。

Byte Buddy建立在

ASM位元組代碼解析器

之上,該解析器已成為Java生态系統中位元組代碼解析的事實上的标準。ASM的 接口來操作位元組碼的生成,通常是使用代表名稱和描述符的字元串值來(是以很簡單)。Byte Buddy提供了一個

StackManipulation

接口來封裝了

visitors

的指令,

StackManipulation

用來和Byte Buddy 的

descriptio

接口互動,把需要的的值提取為适當的格式并與ASM進行互動。此外,每種堆棧操作都知道其對JVM操作數堆棧大小的影響。這樣,就可以将幾種堆棧操作組合在一起,以計算它們對最小堆棧大小的共同要求。可以用一個

ByteCodeAppender

來表示幾種堆棧操作的。位元組碼追加器代表一個代碼塊,并且需要将操作數堆棧留白。另外,位元組代碼追加器應該暴露為本地變量(local variables 就是位元組碼知識裡面的本地變量,)的空間(執行位元組碼指令時,需要關聯使用這些變量)。通常,位元組碼追加器由一個或多個堆棧操作組成。與代碼生成相關的所有類都收集在

net.bytebuddy.implementation.bytecode

包中。

每個位元組碼附加器以接受方法的實作作為入參,然後

apply

到目标方法上。此外,它還接收一個

ASM visitor

,用于注冊該方法的代碼和的執行個體

Implementation.Context

Implementation.Context

允許注冊輔助類型(auxiliary type)。輔助類型表示執行該方法所需的幫助程式類型(就是額外的工具類,以便于其他操作)。比如,一個代理類要調用被修改過的類中的方法。通常會使用

MethodDelegation

為被修改過的類加一個

@SuperCall

注解。

Implementation.Context

是Byte Buddy中為數不多的可變類之一,因為它伴随着的ASM 的method visitor 本事就是可變得(這裡的變是指動态生成,生成時依賴條件)。但是,由于

Implementation.Context

并未公開給公共API,是以也不應該由

ByteCodeAppender

也不應該暴露

Implementation.Context

給使用者使用。

構造方法的

top-level

的API是

Implementation

接口。一個

ByteCodeAppender

,需要一個

Implementation

的是例給出一個

instrumented type

。此外,

Implementation

可以用來注冊額外的方法,字段或代碼塊,在

instrumented type

靜态初始化化的時候。最後,任何實作執行個體都會收到一個執行個體

Implementation.Target

,它提供了一種通路

instrumented type

中屬性的方法,該屬性與具體的類型無關。例如,可以查詢

instrumented type

的 super方法 調用。如果使用者執行

subclass

的生成,則此查詢将傳回真正super方法的。如果使用者進行

type-rebasement,

,則實作目标實作将調用被重新建立方法的原始代碼(原始代碼的方法被重命名,然後被放在新方法中)。

在Byte Buddy中,通過将屬性注冊到可以構造任何類型

DynamicType.Builder

。builder 本身構造了一個

InstrumentedType

執行個體,該執行個體可以擴充

TypeDescription

以允許Byte Buddy的其他元件在建立其類型之前檢視之前的的類型。此外,方法和字段實作以FieldRegistry或 方式注冊MethodRegistry。最後,動态類型建構器将所有收集的資訊TypeWriter提供給與ASM API互動以生成類檔案的所有類型,并将其應用于比對的方法描述 。

編碼約定

Byte Buddy的目标是實作完全不變,除了與大多數易變的ASM庫進行互動的易變類之外。但是,可變元件必須隔離在與ASM互動的範圍内,并且不得暴露給最終使用者。此類執行個體也不應存儲為字段的值。此外,某些元件(例如Byte Buddy的類加載器)由于其作為類加載器的性質而可變。但是,應将Byte Buddy中的所有集合視為不可變的,并且當從公共API傳回集合時,也必須強制執行此屬性。

所有一成不變的類必須實作适當的

hashCode

,并

equals

為對象平等是一些Byte Buddy元件的一個重要概念,方法。例如,任何

Implementation

執行個體都必須僅一次性準備

instrumented type 類型

,因為在Java中兩次注冊具有相同名稱的字段是不合法的。為確定這一點,

Implementation

将檢查任何對象是否與之前有機會準備插入類型的實作是否相等。如果實作内部依賴于不同的對象,則所有這些元件都必須履行其相等的限制,這一點很重要。另外,任何元件都應實施适當的 toString一種改進調試的方法,尤其是在幫助論壇上釋出了使用者的堆棧跟蹤資訊時。使用

ObjectPropertyAssertion

,Byte Buddy可以運作單元測試來确定所有這些方法的正确實作。

Byte Buddy是強面向對象,但從面向函數設計上獲得了一些啟發。不幸的是,作為許多其他庫開發人員使用的元庫,Byte Buddy受到強大的相容性要求的限制,并在Java 6上進行編譯。為模仿函數,

Byte Buddy

經常通過枚舉實作接口,其中枚舉産生

命名函數

。最後,類檔案被用作相關類的容器而不是包。在類檔案中,可以定義

比top-level

類更好的可見性範圍,例如通過允許

protected

隻能由子類或在内部使用另一個類的類中看到的類。同樣,當重構後不再需要一個類時,此分組約定使删除所有相關代碼變得容易。

作為元庫,Byte Buddy試圖提供對API盡可能開放的API,因為無法預期使用範圍。隻要有可能,委托将是優于類擴充的首選擴充機制。

所有代碼

都應記錄在案,這使得此屬性 更易于通過自動檢查

進行驗證

。在Byte Buddy中,将其null用作字段,參數的值或方法傳回值是一種不好的做法。模仿

Java反射API

的描述類型是一個例外,其中null值是常見的。由于描述執行個體(description instances)向最終使用者公開,是以決定将相似性視為比一緻性更重要的因素。是以潛在的null值必須記錄在方法上。對于Byte Buddy,未檢查的異常比檢查的異常更可取。

貢獻

修複錯誤後,隻需 在GitHub上建立拉取請求即可。收到通知後,我們将盡快調查此事。但是,請確定已正确描述了更改和已解決的問題,并提供了一個可重制該問題并證明您的修複程式有效的測試用例。這使我們的工作更加輕松,我們将能夠更快地應用您的更新檔。如果添加新的方法,字段或類型,請確定編寫一些描述其用途的代碼内文檔。如果您應用與性能相關的更改,請使用byte-buddy-benchmark套件。最後,請注意,Byte Buddy的新版本通常是在其自己的分支中開發的。

如果您要提供功能,請先聯系我們,然後再花費大量時間,以便我們可以讨論您的更改在Byte Buddy目前的開發狀态下如何有意義。位元組夥伴旨在穩定地提供更多功能,但我們不會以其穩定性和代碼一緻性為代價來擴充其功能集。但是,不要因本公告而氣disc。如果您對Byte Buddy的源代碼有足夠的了解,能夠實作您想要共享的新功能,那麼您肯定會考慮一下,我們将盡最大努力将其合并到我們的版本中!隻需與我們交談,我們非常樂意歡迎您加入我們。

如果您想為Byte Buddy的文檔,本網頁上的描述甚至本網頁的結構和設計做出貢獻,絕對歡迎您這樣做!我們深信,透徹和最新的文檔是成功項目的關鍵,我們将盡最大努力實作這一信念。隻要可以改善Byte Buddy的可通路性或外觀,甚至可以進行很小的更改,因為最終,該項目是為使用者設計的。隻需克隆此網頁,該網頁托管在項目gh-pages分支的GitHub上。該網頁是使用angular.js和 Twitter的Bootstrap建立的。

路線圖

Byte Buddy已達到1.0版,除了尚不支援的兩個功能外,還被認為是功能完整。随着1.0版的釋出,庫的穩定性和性能得到了極大的重視,并且防禦性地增加了新功能。自然,Java程式設計語言和位元組代碼格式的發展将在未來需要較新的版本,而Byte Buddy的目标是提供一種向後相容的方式來處理舊版本和較新版本的Java。Java 9支援目前仍處于試驗階段。從Java 8開始,Byte Buddy目前不支援以下功能:

類型推斷

Java編譯器可以推斷泛型類型。位元組好友目前不提供此類功能。對類型推斷的支援将允許更好地驗證泛型類型并實作Assigner考慮泛型類型資訊的。不幸的是,此功能在實際應用很少的情況下需要進行大量工作。是以,目前尚未實作。