日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java compile_java中的CompileAPI入门及使用

發(fā)布時間:2023/12/10 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java compile_java中的CompileAPI入门及使用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

介紹

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

使用

通過文件編譯

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

//獲取java編譯器

JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();

//編譯

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

System.out.println(result);

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

編譯參數(shù)依次為

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

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

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

一個或多個Java源程式文件

通過非文件格式編譯

java還提供了編譯其他形式的源文件的功能,如內(nèi)存字符串文本,數(shù)據(jù)庫讀取的文本。

public class JavaFileManagerMain {

public static void main(String[] args) {

//文件路徑

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

//獲取編譯器

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

//獲取文件管理器 參數(shù)依次為錯誤監(jiān)聽器,區(qū)域?qū)ο?#xff0c;編碼

StandardJavaFileManager fileManager =

compiler.getStandardFileManager(null, null, null);

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

Iterable extends JavaFileObject> files =

fileManager.getJavaFileObjectsFromStrings(

Arrays.asList(fullQuanlifiedFileName));

//創(chuàng)建編譯任務(wù) 參數(shù)為錯誤輸出流,文件管理器,錯誤處理器,編譯器選項,參與編譯的class,帶編譯的java文件

JavaCompiler.CompilationTask task = compiler.getTask(

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

//執(zhí)行任務(wù)

Boolean result = task.call();

if (result) {

System.out.println("Succeeded");

}

}

}

接下來實現(xiàn)從內(nèi)存中讀取待編譯對象

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!");

}

}

//通過字符串創(chuàng)建一個待編譯對象

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;

}

}

結(jié)果編譯成功。

實現(xiàn)在運行期編譯及加載類

定義源代碼存儲類

/**

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

*/

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;

}

}

定義編譯結(jié)果存儲類

/**

* 存儲編譯之后的class內(nèi)容

*/

public class JavaTargetFileObject extends SimpleJavaFileObject {

/**

* Compiler編譯后的byte數(shù)據(jù)會存在這個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的方法。

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

*

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

*

* @return

* @throws IOException

*/

@Override

public OutputStream openOutputStream() throws IOException {

return this.byteArrayOutputStream;

}

/**

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

*/

public byte[] getBytes() {

return this.byteArrayOutputStream.toByteArray();

}

}

定義自己的文件管理器

/**

* 內(nèi)存文件管理器

* @see JavaTargetFileObject

*/

public class ClassFileManager extends ForwardingJavaFileManager {

/**

* 存儲編譯后的代碼數(shù)據(jù)

*/

private JavaTargetFileObject classJavaFileObject;

protected ClassFileManager(JavaFileManager fileManager) {

super(fileManager);

}

/**

* 編譯后加載類

*

* 返回一個匿名的SecureClassLoader:

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

*/

@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,編譯器會將編譯結(jié)果寫進(jìn)去

*/

@Override

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

throws IOException {

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

return this.classJavaFileObject;

}

}

定義一個實現(xiàn)類編譯和加載

/**

* 運行時編譯

*/

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);

}

}

/**

* 關(guān)閉fileManager

*

* @throws IOException

*/

public void close() throws IOException {

this.fileManager.close();

}

}

總結(jié)

以上是生活随笔為你收集整理的java compile_java中的CompileAPI入门及使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。