java compile_java中的CompileAPI入門及使用

介紹

java5之前我們可以通過java提供的tools.jar來操作java編譯器,java6提供了新的API,讓我們可以更方便的調用。包名為javax.tools。

使用

通過文件編譯

String filePath = "D:\\Client.java";

//獲取java編譯器

JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();

//編譯

int result = javaCompiler.run(null, null, null, filePath);

System.out.println(result);

結果為0表示編譯成功,在相同目錄下生成了Client.class文件。

編譯參數依次為

java編譯器提供參數,如果為null,以System.in代替

得到Java編譯器的輸出信息,如果為null,以System.out代替

接收編譯器的錯誤信息,如果為null,以System.err代替

一個或多個Java源程式文件

通過非文件格式編譯

java還提供了編譯其他形式的源文件的功能,如內存字符串文本,數據庫讀取的文本。

public class JavaFileManagerMain {

public static void main(String[] args) {

//文件路徑

String fullQuanlifiedFileName = "D:\\Client.java";

//獲取編譯器

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

//獲取文件管理器 參數依次為錯誤監聽器,區域對象,編碼

StandardJavaFileManager fileManager =

compiler.getStandardFileManager(null, null, null);

//通過文件全路徑獲取要編譯的文件對象

Iterable extends JavaFileObject> files =

fileManager.getJavaFileObjectsFromStrings(

Arrays.asList(fullQuanlifiedFileName));

//創建編譯任務 參數為錯誤輸出流,文件管理器,錯誤處理器,編譯器選項,參與編譯的class,帶編譯的java文件

JavaCompiler.CompilationTask task = compiler.getTask(

null, fileManager, null, null, null, files);

//執行任務

Boolean result = task.call();

if (result) {

System.out.println("Succeeded");

}

}

}

接下來實現從內存中讀取待編譯對象

public class StringObject extends SimpleJavaFileObject {

private String content = null;

protected StringObject(String className, String contents) throws URISyntaxException {

super(new URI(className), Kind.SOURCE);

this.content = contents;

}

@Override

public CharSequence getCharContent(boolean ignoreEncodingErrors) {

return content;

}

}

public class StringClassCompilerMain {

public static void main(String[] args) {

JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();

StandardJavaFileManager standardJavaFileManager = javaCompiler.getStandardFileManager(null, null, null);

JavaFileObject testFile = generateTest();

Iterable extends JavaFileObject> classes = Arrays.asList(testFile);

JavaCompiler.CompilationTask task = javaCompiler.getTask(null, standardJavaFileManager, null, null, null, classes);

if (task.call()) {

System.out.println("success");

} else {

System.out.println("failure!");

}

}

//通過字符串創建一個待編譯對象

private static JavaFileObject generateTest() {

String contents = "package com.imooc.sourcecode.java.javacompile.test3;" +

"class Test {\n" +

" public static void main(String[] args) {\n" +

" System.out.println(\"success\");\n" +

" }\n" +

"}\n";

StringObject so = null;

try {

so = new StringObject("com.imooc.sourcecode.java.javacompile.test3.Test", contents);

} catch (URISyntaxException e) {

e.printStackTrace();

}

return so;

}

}

結果編譯成功。

實現在運行期編譯及加載類

定義源代碼存儲類

/**

* 待編譯對象 存儲待編譯的字符串

*/

public class JavaSourceFileObject extends SimpleJavaFileObject {

//表示java源代碼

private CharSequence content;

protected JavaSourceFileObject(String className, String content) {

super(URI.create("string:///" + className.replaceAll("\\.", "/") + Kind.SOURCE.extension), Kind.SOURCE);

this.content = content;

}

/**

* 獲取需要編譯的源代碼

*

* @param ignoreEncodingErrors

* @return

* @throws IOException

*/

@Override

public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {

return content;

}

}

定義編譯結果存儲類

/**

* 存儲編譯之后的class內容

*/

public class JavaTargetFileObject extends SimpleJavaFileObject {

/**

* Compiler編譯后的byte數據會存在這個ByteArrayOutputStream對象中,

* 后面可以取出,加載到JVM中。

*/

private ByteArrayOutputStream byteArrayOutputStream;

public JavaTargetFileObject(String className, Kind kind) {

super(URI.create("string:///" + className.replaceAll("\\.", "/") + kind.extension), kind);

this.byteArrayOutputStream = new ByteArrayOutputStream();

}

/**

* 覆蓋父類SimpleJavaFileObject的方法。

* 該方法提供給編譯器結果輸出的OutputStream。

*

* 編譯器完成編譯后,會將編譯結果輸出到該 OutputStream 中,我們隨后需要使用它獲取編譯結果

*

* @return

* @throws IOException

*/

@Override

public OutputStream openOutputStream() throws IOException {

return this.byteArrayOutputStream;

}

/**

* FileManager會使用該方法獲取編譯后的byte,然后將類加載到JVM

*/

public byte[] getBytes() {

return this.byteArrayOutputStream.toByteArray();

}

}

定義自己的文件管理器

/**

* 內存文件管理器

* @see JavaTargetFileObject

*/

public class ClassFileManager extends ForwardingJavaFileManager {

/**

* 存儲編譯后的代碼數據

*/

private JavaTargetFileObject classJavaFileObject;

protected ClassFileManager(JavaFileManager fileManager) {

super(fileManager);

}

/**

* 編譯后加載類

*

* 返回一個匿名的SecureClassLoader:

* 加載由JavaCompiler編譯后,保存在ClassJavaFileObject中的byte數組。

*/

@Override

public ClassLoader getClassLoader(Location location) {

return new SecureClassLoader() {

@Override

protected Class> findClass(String name) throws ClassNotFoundException {

byte[] bytes = classJavaFileObject.getBytes();

return super.defineClass(name, bytes, 0, bytes.length);

}

};

}

/**

* 給編譯器提供JavaClassObject,編譯器會將編譯結果寫進去

*/

@Override

public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling)

throws IOException {

this.classJavaFileObject = new JavaTargetFileObject(className, kind);

return this.classJavaFileObject;

}

}

定義一個實現類編譯和加載

/**

* 運行時編譯

*/

public class DynamicCompiler {

private JavaFileManager fileManager;

public DynamicCompiler() {

this.fileManager = initManger();

}

private JavaFileManager initManger() {

if (fileManager != null) {

return fileManager;

} else {

JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();

DiagnosticCollector diagnosticCollector = new DiagnosticCollector<>();

fileManager = new ClassFileManager(javaCompiler.getStandardFileManager(diagnosticCollector, null, null));

return fileManager;

}

}

/**

* 編譯源碼并加載,獲取Class對象

*

* @param fullName

* @param sourceCode

* @return

* @throws ClassNotFoundException

*/

public Class compileAndLoad(String fullName, String sourceCode) throws ClassNotFoundException {

JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();

List javaFileObjectList = new ArrayList<>();

javaFileObjectList.add(new JavaSourceFileObject(fullName, sourceCode));

boolean result = javaCompiler

.getTask(null, fileManager, null, null, null, javaFileObjectList)

.call();

if (result) {

return this.fileManager.getClassLoader(null).loadClass(fullName);

} else {

return Class.forName(fullName);

}

}

/**

* 關閉fileManager

*

* @throws IOException

*/

public void close() throws IOException {

this.fileManager.close();

}

}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/260341.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/260341.shtml
英文地址,請注明出處:http://en.pswp.cn/news/260341.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

《Two Days DIV + CSS》讀書筆記——CSS選擇器

1.1.2 CSS選擇器 CSS 選擇器最基本的有四種&#xff1a;標簽選擇器、ID 選擇器、類選擇器、通用選擇器。 【標簽選擇器】 一個完整的 HTML 頁面由很多不同的標簽組成&#xff0c;而標簽選擇器&#xff0c;則是決定哪些標簽采用相應的 CSS 樣式&#xff0c;比如&#xff0c;在 s…

TempDB為什么要根據CPU數目來決定文件個數

在SQL Server的世界中&#xff0c;SQL Server在Windows之上有一套自己的任務調度和資源分配系統&#xff0c;這使得SQL Server作為Windows的一個進程&#xff0c;卻可以處理大量的并發&#xff0c;這些任務調度和資源分配非常像一個操作系統&#xff0c;因此SQL Server在Window…

python基礎到實踐_一本書搞定Python入門到實踐

題圖&#xff1a;Photo by Aaron Burden on Unsplash上周介紹了幾本Python從入門到進階書籍&#xff0c;今天推薦一本入門好書《Python編程&#xff1a;從入門到實踐》&#xff0c;適合零基礎小白&#xff0c;也適合有其它語言背景的程序員。書中有哪些亮點&#xff1f;2016年出…

Linux網卡eth0變成eth1修改方法

由于換了主板&#xff0c;集成網卡mac地址變了&#xff0c;70-persistent-net.rules中仍然保留了老網卡的內容&#xff0c;新網卡則被識別為eth1。 將表示老網卡的行注釋掉&#xff0c;然后將表示新網卡的行中eth1改成eth0&#xff0c;在把網卡配置文件ifcfg-eth0的mac地址改成…

java微博模擬登陸_java 模擬登錄新浪微博(通過cookie)

這幾天一直在研究新浪微博的爬蟲&#xff0c;發現爬取微博的數據首先要登錄。本來打算是通過賬號和密碼模擬瀏覽器登錄。但是現在微博的登錄機制比較復雜。通過賬號密碼還沒有登錄成功QAQ。所以就先記錄下&#xff0c;通過cookie直接訪問自己的微博主頁。微博登錄的認證過程微博…

硬盤結構,主引導記錄MBR,硬盤分區表DPT,主分區、擴展分區和邏輯分區,電腦啟動過程...

filex的文件系統看的云里霧里&#xff0c;還是先總結下FAT的一些基本知識吧。硬盤結構硬盤有很多盤片組成&#xff0c;每個盤片的每個面都有一個讀寫磁頭。如果有N個盤片。就有2N個面&#xff0c;對應2N個磁頭(Heads)&#xff0c;從0、1、2開始編號。每個盤片的半徑均為固定值R…

最全面 Nginx 入門教程 + 常用配置解析

轉自 http://blog.csdn.net/shootyou/article/details/6093562 Nginx介紹和安裝 一個簡單的配置文件 模塊介紹 常用場景配置 進階內容 參考資料 Nginx介紹和安裝 Nginx是一個自由、開源、高性能及輕量級的HTTP服務器及反轉代理服務器&#xff0c; 其性能與IMAP/POP3代理服務器…

linux 客戶機中不支持 unity_婚姻中的不理解,來源于夫妻雙方情感支持的不同

很多女性在婚姻中往往覺得無法得到丈夫的理解&#xff0c;當遇到一些生活或者工作上的問題的時候&#xff0c;她們想要在情感上得到丈夫的支持和理解。但是很多丈夫對此可能并不了解和理解&#xff0c;更傾向于用理性幫助妻子解決問題。而女性所需要的幫助可能并不是解決問題的…

Linux中使用crontab命令啟用自定義定時任務

一 簡介Linux下的任務調度分為兩類&#xff0c;系統任務調度和用戶任務調度系統任務調度&#xff1a;系統需要定期執行的任務&#xff0c;比如重啟、日志清理等&#xff0c;其配置文件是&#xff1a;/etc/crontab用戶任務調度&#xff1a;某個用戶需要定期執行的任務。用戶可以…

java 循環標記_深入淺析Java 循環中標簽的作用

continue和break可以改變循環的執行流程&#xff0c;但在多重循環中&#xff0c;這兩條語句無法直接從內層循環跳轉到外層循環。在C語言中&#xff0c;可以通過goto語句實現多重循環的跳轉&#xff0c;但在非循環結構中使用goto語句會使程序的結構紊亂&#xff0c;可讀性變差。…

JS,Jquery 調用 C#WebService

1&#xff0c;需要在服務下面把代碼的注釋去掉 // 若要允許使用 ASP.NET AJAX 從腳本中調用此 Web 服務&#xff0c;請取消對下行的注釋。   //[System.Web.Script.Services.ScriptService] 2,JS 調用方法如下 var request <?xml version"1.0" encoding"…

iOS tabview 適配問題

ios7的UITableView實現ios6的圓角效果 iOS7 UITableView做成類似iOS6風格 在iOS7的時候我們會發現cell的默認線條會向右偏移&#xff0c;使左邊空出了一些位置&#xff0c;這時候我們可以調用如下的方法來解決。這樣我們的cell就會和iOS6前的一樣鋪滿整個寬度了。 if ([tableVi…

PHP學習總結(14)——PHP入門篇之常用運算符

一、什么是運算符什么是運算符&#xff1f;運算符是告訴PHP做相關運算的標識符號。例如&#xff0c;你需要計算123乘以456等于多少&#xff0c;這時候就需要一個符號&#xff0c;告訴服務器&#xff0c;你需要做乘法運算。PHP中的運算符有哪些&#xff1f;PHP運算符一般分為算術…

百度時間顯示_文章的發布時間對百度優化網站重要嗎

文章的發布時間對百度優化網站重要嗎&#xff1f;這個問題&#xff0c;相信很多初做網站優化的萌新朋友都會問到&#xff0c;以小匠個人的經歷來分享這個問題的經驗&#xff0c;小匠認為&#xff0c;文章的發布時間對優化網站是非常重要的&#xff0c;下面小匠將從實際經歷來給…

循環鏈表解決約瑟夫環問題

約瑟夫環問題可以簡單的使用數組的方式實現&#xff0c;但是現在我使用循環鏈表的方法來實現&#xff0c;因為上午看到一道面試題規定使用循環鏈表解決約瑟夫環問題。 什么是約瑟夫環&#xff1f; “約瑟夫環是一個數學的應用問題&#xff1a;已知n個人&#xff08;以編號1&…

java 什么時候進行垃圾回收_java什么時候進行垃圾回收,垃圾回收的執行流程

java的垃圾回收分為三個區域新生代 老年代 永久代一個對象實例化時 先去看伊甸園有沒有足夠的空間如果有 不進行垃圾回收 ,對象直接在伊甸園存儲.如果伊甸園內存已滿,會進行一次minor gc然后再進行判斷伊甸園中的內存是否足夠如果不足 則去看存活區的內存是否足夠.如果內存足夠…

常用的webservice接口

商業和貿易&#xff1a; 1、股票行情數據 WEB 服務&#xff08;支持香港、深圳、上海基金、債券和股票&#xff1b;支持多股票同時查詢&#xff09; Endpoint: http://webservice.webxml.com.cn/WebServices/StockInfoWS.asmx Disco: http://webservice.webxml.com.cn/WebServ…

基于HTML5 Canvas 實現矢量工控風機葉輪旋轉

之前在拓撲上的應用都是些靜態的圖元&#xff0c;今天我們將在拓撲上設計一個會動的圖元——葉輪旋轉。 先看看最后我們實現的效果&#xff1a;http://www.hightopo.com/demo/fan/index.html 我們先來看下這個葉輪模型長什么樣 從模型上看&#xff0c;這個葉輪模型有三個葉片&a…

java 并發模型總類_java并發編程系列-內存模型基礎

java線程之間的通信對程序開發人員是完全透明的&#xff0c;內存的可見性問題很容易困擾很多開發人員。本篇博文將揭開java內存模型的神秘面紗&#xff0c;來看看內存模型到底是怎樣的。并發編程模型的分類并發編程中需要處理的兩個關鍵問題&#xff1a;線程之間如何通信線程之…

python調用java的jar包_python調用java的jar包報錯127

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓最近在弄python需要調用到Java的jar包&#xff0c;按照網上的教程走&#xff0c;最后總是報錯No matching overloads found for [init in find. at native\common\jp_method.cpp:127Java&#xff1a;package aes;import com.sun.cr…