深度探討Java字節代碼的操縱方法

Java作爲業界使用最爲普遍的語言之一, 深得衆多軟件廠商和開發者的推崇, 但是關於Java語言的深度瞭解和運用, 本文爲IBM工程師成富編寫的《Java深度歷險》的第一部分Java字節代碼的操縱, 編寫Java源代碼, 再利用IDE提供的功能直接運轉Java順序就可以了。 java), IDE會擔任調用Java的編譯器把Java源代碼編譯成平臺無關的字節代碼(bytecode), 以類文件的形式保存在磁盤上(. class)。 Java虛擬機(JVM)會擔任把Java字節代碼加載並執行。 Java經過這種方式來實現其“編寫一次, 四處運轉(Writeonce, runanywhere)”的目的。 JVM中的類加載器會擔任從包括字節代碼的字節數組(byte[])中定義出Java類。 可能會需要動態的生成Java字節代碼, 或是對已有的Java字節代碼停止修改。 這個時候就需要用到本文中將要介紹的相關技術。   動態編譯Java源文件  在普通情況下, 開發人員都是在順序運轉之前就編寫完成了全部的Java源代碼並且成功編譯。 對有些使用來說, Java源代碼的內容在運轉時辰才幹確定。 再由JVM來加載執行。 由系統在後臺編譯、運轉並停止斷定。 使用的做法是直接在順序中調用Java編譯器。 可以使用JDK中的工具類com. sun. Main, 不過該工具類只能編譯寄存在磁盤上的文件,   另外一個可用的工具是EclipseJDTCore提供的編譯器。 這是EclipseJava開發環境使用的增量式Java編譯器, Play框架在內部使用了JDT的編譯器來動態編譯Java源代碼。 在開發模式下, 因而在修改代碼之後, 刷新頁面就可以看到變化。 需要確保JDK中的tools. jar在使用的CLASSPATH中。 是關於如何在Java外面做四則運算, 比如求出來(3+4)7-10的值。 普通的做法是剖析輸出的運算表達式, 考慮到括號的存在和運算符的優先級等成果, 另外一種做法是可以用JSR223引入的腳本語言支持, 直接把輸出的表達式當做JavaScript或是JavaFX腳原本執行, 上面的代碼使用的做法是動態生成Java源代碼並編譯, 接着加載Java類來執行並獲取結果。 這種做法完全使用Java來實現。   上面的代碼給出了使用動態生成的Java字節代碼的基本模式, 即經過類加載器來加載字節代碼, 創立Java類的對象的實例,   Java字節代碼加強  Java字節代碼加強指的是在Java字節代碼生成之後, 這種做法相當於對使用順序的二進制文件停止修改。 註解在Java源代碼中聲明瞭需要加強的行爲及相關的元數據, 用過JavaBeans的人可能對其中那些必需添加的getter/setter方法感到很繁瑣, 而經過字節代碼加強, 開發人員只需要聲明Bean中的屬性即可, getter/setter方法可以經過修改字節代碼來自動添加。 用過JPA的人, 在調試順序的時候, 會發現實體類中被添加了一些額外的域和方法。 首先介紹一下表示一個Java類或接口的字節代碼的組織形式。   類文件  如上所示, 一個類或接口的字節代碼使用的是一種鬆懈的組織構造, 關於可能包括多個條目的內容, 如所實現的接口、域、方法和屬性等, 是以數組來表示的。 不同的內容類型, 關於開發人員來說, 直接操縱包括字節代碼的字節數組的話, 開發效率比擬低, 這些類庫包括ASM、cglib、serp和BCEL等。 比如考慮上面一個複雜的需求, 在一個Java類的所有方法執行之前輸出相應的日誌。 熟悉AOP的人都曉得, 相關的代碼如下:  從ClassWriter就可以獲取到包括加強之後的字節代碼的字節數組, 加強部分的邏輯比擬複雜, 只是遍歷Java類中的所有方法並添加對System. println方法的調用。 在字節代碼中, 而要做的是生成調用System. 並把這些指令插入到指令集合的最前面。 ASM對這些指令做了抽象, ASM提供了一個工具類ASMifierClassVisitor, 當需要加強某個類的時候, 可以先在源代碼上做出修改, 在JVM執行之前。 當獲取到Java類的字節代碼之後, 先停止加強處理,   由於存在着少量對Java字節代碼停止修改的需求, lang. instrument包並在JDK6中失掉了進一步的加強。 這個類會包括一個premain方法。 JVM在啓動的時候會首先執行代理類的premain方法, 再執行Java順序本身的main方法。 在premain方法中就可以對順序本身的字節代碼停止修改。 JDK6中還允許在JVM啓動之後動態添加代理。 java. instrument包支持兩種修改的場景, 一種是重定義一個Java類, 即完全交流一個Java類的字節代碼;另外一種是轉換已有的Java類, 相當於前面提到的類字節代碼加強。 首先需要實現java. lang. instrument. ClassFileTransformer接口來完成對已有Java類的轉換。   把該代理類打成一個jar包, 運轉Java順序的時候, 添加JVM啓動參數-javaagent:myagent. jar。 這樣的話, 完成相關的轉換操作。 可以很容易的對二進制分發的Java順序停止修改, 十分適宜於性能剖析、調試跟蹤和日誌記載等義務。 另外一個十分重要的作用是把開發人員從繁瑣的Java語法中解放出來。 開發人員應該只需要擔任編寫與業務邏輯相關的重要代碼。 關於那些只是由於語法要求而添加的, 或是模式固定的代碼, 完全可以將其字節代碼動態生成出來。 字節代碼加強和源代碼生成是不同的概念。 源代碼生成之後, 就已經成爲了順序的一部分, 開發人員需要去維護它:要麼手工修改生成出來的源代碼, 要麼重重生成。 關於開發人員是完全透明的。 妥善使用Java字節代碼的操縱技術, 可以更好的解決某一類開發成果。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章