十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
(Write once, run anywhere)” 的目標。Java類文件中包含的字節(jié)代碼可以被不同平臺上的JVM所使用。Java字節(jié)代碼不僅可以以文件形式存在于磁盤上,也可以通過網(wǎng)絡方式來下載,還可以只存在于內(nèi)存中。JVM中的類加載器會負責從包含字節(jié)代碼的字節(jié)數(shù)組(byte[])中定義出Java類。在某些情況下,可能會需要動態(tài)的生成 Java字節(jié)代碼,或是對已有的Java字節(jié)代碼進行修改。這個時候就需要用到本文中將要介紹的相關技術。首先介紹一下如何動態(tài)編譯Java源文件。
創(chuàng)新互聯(lián)擁有網(wǎng)站維護技術和項目管理團隊,建立的售前、實施和售后服務體系,為客戶提供定制化的網(wǎng)站設計、成都網(wǎng)站建設、網(wǎng)站維護、四川電信機房托管解決方案。為客戶網(wǎng)站安全和日常運維提供整體管家式外包優(yōu)質(zhì)服務。我們的網(wǎng)站維護服務覆蓋集團企業(yè)、上市公司、外企網(wǎng)站、商城開發(fā)、政府網(wǎng)站等各類型客戶群體,為全球1000+企業(yè)提供全方位網(wǎng)站維護、服務器維護解決方案。
動態(tài)編譯Java源文件
在一般情況下,開發(fā)人員都是在程序運行之前就編寫完成了全部的Java源代碼并且成功編譯。對有些應用來說,Java源代碼的內(nèi)容在運行時刻才能確定。這個時候就需要動態(tài)編譯源代碼來生成Java字節(jié)代碼,再由JVM來加載執(zhí)行。典型的場景是很多算法競賽的在線評測系統(tǒng)(如PKU JudgeOnline),允許用戶上傳Java代碼,由系統(tǒng)在后臺編譯、運行并進行判定。在動態(tài)編譯Java源文件時,使用的做法是直接在程序中調(diào)用Java編譯器。
JSR 199引入了Java編譯器API。如果使用JDK 6的話,可以通過此API來動態(tài)編譯Java代碼。比如下面的代碼用來動態(tài)編譯最簡單的Hello World類。該Java類的代碼是保存在一個字符串中的。
public class CompilerTest {
public static void main(String[] args) throws Exception {
String source = "public class Main { public static void main(String[] args) {System.out.println(\"Hello World!\");} }";
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
StringSourceJavaObject sourceObject = new CompilerTest.StringSourceJavaObject("Main", source);
Iterable extends JavaFileObject fileObjects = Arrays.asList(sourceObject);
CompilationTask task = compiler.getTask(null, fileManager, null, null, null, fileObjects);
boolean result = task.call();
if (result) {
import?javax.tools.*;
import?java.io.*;
/**
*?@author?hardneedl
*/
final?public?class?MyCompile?{
/**
*?@param?args?命令行參數(shù)只有1個,即待編譯的源代碼文件的絕對路徑
*?@throws?FileNotFoundException
*/
public?static?void?main(String...?args)?throws?FileNotFoundException?{
JavaCompiler?compiler?=?ToolProvider.getSystemJavaCompiler();
int?r?=?compiler.run(null,null,null,args[0]);
System.out.println(r?==?0??"成功":"失敗");
}
}
Java代碼正常是靜態(tài)編譯成字節(jié)碼,由對應平臺的JVM加載執(zhí)行,靜態(tài)編譯無法動態(tài)擴展功能。動態(tài)編譯有兩種方式實現(xiàn):
從源碼編譯,需要調(diào)用Java Compiler,程序需要運行于JDK(而不是JRE)之上。
動態(tài)字節(jié)碼生成技術(如CGLib、ASM)創(chuàng)建類。
動態(tài)編譯可以簡化代碼,增強類功能,但也帶來了代碼復雜度,線上不易維護。
Java代碼的編譯與反編譯
2017-02-21Hollis數(shù)盟
一、什么是編譯
1、利用編譯程序從源語言編寫的源程序產(chǎn)生目標程序的過程。
2、用編譯程序產(chǎn)生目標程序的動作。編譯就是把高級語言變成計算機可以識別的2進制語言,計算機只認識1和0,編譯程序把人們熟悉的語言換成2進制的。編譯程序把一個源程序翻譯成目標程序的工作過程分為五個階段:詞法分析;語法分析;語義檢查和中間代碼生成;代碼優(yōu)化;目標代碼生成。主要是進行詞法分析和語法分析,又稱為源程序分析,分析過程中發(fā)現(xiàn)有語法錯誤,給出提示信息。
二、什么是反編譯
計算機軟件反向工程(Reverseengineering)也稱為計算機軟件還原工程,是指通過對他人軟件的目標程序(可執(zhí)行程序)進行“逆向分析、研究”工作,以推導出他人的軟件產(chǎn)品所使用的思路、原理、結構、算法、處理過程、運行方法等設計要素,某些特定情況下可能推導出源代碼。反編譯作為自己開發(fā)軟件時的參考,或者直接用于自己的軟件產(chǎn)品中。
三、Java類的編譯與反編譯
我們在最初學習Java的時候,會接觸到兩個命令:javac和java,那個時候我們就知道,javac是用來編譯Java類的,就是將我們寫好的helloworld.java文件編譯成helloworld.class文件。
class文件打破了C或者C++等語言所遵循的傳統(tǒng),使用這些傳統(tǒng)語言寫的程序通常首先被編譯,然后被連接成單獨的、專門支持特定硬件平臺和操作系統(tǒng)的二進制文件。通常情況下,一個平臺上的二進制可執(zhí)行文件不能在其他平臺上工作。而Javaclass文件是可以運行在任何支持Java虛擬機的硬件平臺和操作系統(tǒng)上的二進制文件。
那么反編譯呢,就是通過helloworld.class文件得到java文件(或者說是程序員能看懂的Java文件)
四、什么時候會用到反編譯
1、我們只有一個類的class文件,但是我們又看不懂Java的class文件,那么我們可以把它反編譯成我們可以看得懂的文件。
2、學習Java過程中,JDK的每個版本都會加入越來越多的語法糖,有些時候我們想知道Java一些實現(xiàn)細節(jié),我們可以借助反編譯。
五、反編譯工具
1、javap
2、Jad:官網(wǎng)(墻裂推薦)
客戶端:
可以在官網(wǎng)下載可執(zhí)行文件,找到對應的操作系統(tǒng)的對應版本,然后進行安裝使用。
因為我使用的是linux操作系統(tǒng),所以我下載的是Linux版本的工具,這個工具下載好之后會有一個執(zhí)行文件,只要在執(zhí)行文件所在目錄執(zhí)行./jadhelloworld.class就會在當前目錄下生成helloworld.jad文件,該文件里就是我們很熟悉的Java代碼
Eclipse插件:
下載地址在官網(wǎng)下載插件的jar包,然后將jar包放到eclipse的plugins目錄下‘在打開Eclipse,Eclipse-Window-Preferences-Java,此時你會發(fā)現(xiàn)會比原來多了一個JadClipse的選項,單擊,在Pathtodecompiler中輸入你剛才放置jad.exe的位置,也可以制定臨時文件的目錄。當然在JadClipse下還有一些子選項,如Debug,Directives等,按照默認配置即可?;九渲猛戤吅?,我們可以查看一下class文件的默認打開方式,Eclipse-Window-Preferences-General-Editors-FileAssociations我們可以看到class文件的打開方式有兩個,JadClipse和Eclipse自帶的ClassFileViewer,而JadClipse是默認的。全部配置完成,下面我們可以查看源碼了,選擇需要查看的類,按F3即可查看源碼