簡體   English   中英

Java中的程序代碼修改(例如,變量提取)

[英]Programatic code modification (e.g. variable extraction) in Java

我知道可以使用Reflection做一些不錯的事情,例如調用方法或更改字段的值。 但是,是否可以在運行時和以編程方式進行更大量的代碼修改?

例如,如果我有一個方法:

public void foo(){
    this.bar = 100;
}

我可以編寫一個程序來修改此方法的內在特性,注意到它為字段分配了一個常量,並將其轉換為以下內容:

public int baz = 100;

public void foo(){
    this.bar = baz;
}

也許Java並不是真正用於執行此類操作的語言-否則,我願意接受有關語言的建議,這些建議將允許我基本上以這種方式重新解析或檢查代碼,並能夠如此精確地對其進行更改。 我可能在這里做夢,所以請告訴我是否也是這種情況。

只是添加一個朋友的建議-Apache Commons的BCEL看起來很棒:

http://commons.apache.org/bcel/manual.html

字節碼工程庫(Apache Commons BCEL™)旨在為用戶提供一種方便的方法來分析,創建和操作(二進制)Java類文件(以.class結尾的文件)。 類由對象表示,這些對象包含給定類的所有符號信息:特別是方法,字段和字節碼指令。 這樣的對象可以從現有文件中讀取,可以通過程序(例如,運行時的類加載器)進行轉換,然后再次寫入文件中。 一個更有趣的應用程序是在運行時從頭開始創建類。 如果您想了解Java虛擬機(JVM)和Java .class文件的格式,則字節碼工程庫(BCEL)也可能很有用。

您正在尋找允許您進行字節碼操作的軟件,有幾種框架可以實現此目的,但是目前最著名的兩個是:

在Java類中在運行時執行字節碼修改時,請記住以下幾點:

  • 如果在類加載器加載類后更改類的字節碼,則必須找到一種方法來重新加載其類定義(通過類加載技巧或使用熱交換功能)

  • 如果更改類接口(例如添加新方法或字段),則只能通過反射來訪問它們。

可以公平地說,Java並不是出於這個目的而設計的,但是您可以潛在地做到這一點。 如何以及何時取決於練習的最終目的。 有兩個選擇:

你的意思是這樣嗎?

String script1 = "println(\"OK!\");";
eval( script1 );
script1 += "println(\"... well, maybe NOT OK after all\");";
eval( script2 );

輸出:

OK!
OK!
... well, maybe NOT OK after all

...使用Java腳本擴展。 Groovy之類的事情可能會讓您做自己想做的事情。 我已經編寫了一個腳本擴展,可以自己幾乎無縫地通過反射與Java集成。 如果您對詳細信息感興趣,請與我聯系。

您想研究程序轉換系統(PTS) ,它提供了用於在源代碼級別解析和轉換語言的常規工具。 PTS提供了重寫規則,實際上使用目標語言的表面語法說:“如果看到此模式,則用該模式替換”。 這是使用完整的解析器完成的,因此重寫規則實際上是根據語言語法而不是文本執行的; 與基於正則表達式的工具不同,此類重寫規則顯然不會嘗試在注釋中修改類似代碼的文本。

我們的DMS軟件再造工具包就是其中之一。 它不僅提供常規的解析,AST構建和prettyprinting(再現帶有注釋的可編譯源代碼),而且還支持符號表以及控制和數據流分析。 幾乎所有有趣的轉換都需要這些。 DMS還具有各種Java語言以及許多其他語言的前端。

存在字節碼轉換器是因為它們易於構建。 “解析”字節碼非常容易。 當然,您不能使用字節碼轉換器進行永久的源更改,因此它的用途要少得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM