(Write once, run anywhere)” 的目標(biāo)。Java類文件中包含的字節(jié)代碼可以被不同平臺上的JVM所使用。Java字節(jié)代碼不僅可以以文件形式存在于磁盤上,也可以通過網(wǎng)絡(luò)方式來下載,還可以只存在于內(nèi)存中。JVM中的類加載器會負(fù)責(zé)從包含字節(jié)代碼的字節(jié)數(shù)組(byte[])中定義出Java類。在某些情況下,可能會需要動態(tài)的生成 Java字節(jié)代碼,或是對已有的Java字節(jié)代碼進行修改。這個時候就需要用到本文中將要介紹的相關(guān)技術(shù)。首先介紹一下如何動態(tài)編譯Java源文件。
10年積累的成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè)經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站設(shè)計后付款的網(wǎng)站建設(shè)流程,更有電白免費網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
動態(tài)編譯Java源文件
在一般情況下,開發(fā)人員都是在程序運行之前就編寫完成了全部的Java源代碼并且成功編譯。對有些應(yīng)用來說,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) {
1.將你這段字符串輸出到一個文件里,用Java類文件的方式命名。
2.調(diào)用外部javac命令將該文件編譯。
3.用類加載器(ClassLoad)動態(tài)加載新的class文件并用Class.forName()注冊該類,然后就可以正常使用了。
上面的每一步都能在baidu中找到實現(xiàn)方法,自己發(fā)揮吧。
首先你可以使用輸入輸出流(或者你說的可能是要用反射得到程序結(jié)果來解析)解析做出*.Java文件。
然后可以使用runtime調(diào)用Dos下的java編譯命令編譯取得class文件。
然后使用classloader,反射等組合執(zhí)行生成的class文件。
后臺獲取這段代碼之后,將其自動補全成一個java類。
然后將其用io生成為 .java文本文件
之后調(diào)用
Runtime.getRuntime().exec("x:/javac.exe xx.java ...") 編譯
最后使用反射或者代理調(diào)用這個類文件得到結(jié)果
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??"成功":"失敗");
}
}
在javascript中eval()可以實現(xiàn)字符串轉(zhuǎn)代碼,java中需要使用動態(tài)編譯。
把獲得的字符串寫入一個臨時文件中,然后編譯它,在調(diào)用其中的函數(shù)。
我們把要轉(zhuǎn)換的字符串構(gòu)造一個完整的類:如果方法是有返回值的.則:
public object eval(string str){
//生成java文件
string s = "class temp{";
s += "object rt(){"
s += "myclass mc = new myclass();"
s += " return mc."+str+"();";
s += "}"
s +="}";
file f = new file("temp.java");
printwriter pw = new printwriter(new filewriter(f));
pw.println(s);
pw.close();
//動態(tài)編譯
com.sun.tools.javac.main javac = new com.sun.tools.javac.main();
string[] cpargs = new string[] {"-d", "所在目錄","temp.java"};
int status = javac.compile(cpargs);
if(status!=0){
system.out.println("沒有成功編譯源文件!");
return null;
}
//調(diào)用temp的rt方法返回結(jié)果:
myclassloader mc = new myclassloader();
class clasz = mc.loadclass("test.class",true);
method rt = clasz.getmethod("rt", new class[]{ string[].class });
return rt.invoke(null, new object[] { new string[0] });
//如果方法沒有返回就直接調(diào)用
}
我們可以先寫好多個重載的eval,有返回值和沒有返回值的.以及可以傳遞參數(shù)的.
這樣我們就可以用字符串轉(zhuǎn)換為java的語句來執(zhí)行.
當(dāng)前文章:java文本代碼動態(tài)執(zhí)行 java動態(tài)執(zhí)行
分享路徑:http://www.chinadenli.net/article8/doogjop.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計公司、動態(tài)網(wǎng)站、網(wǎng)站排名、面包屑導(dǎo)航、外貿(mào)建站、外貿(mào)網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)