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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java_动态加载

發(fā)布時間:2023/12/19 java 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java_动态加载 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Java類動態(tài)加載(一)——java源文件動態(tài)編譯為class文件
最近在做java動態(tài)加載這方面的工作,起初也遇到了很多困難。網(wǎng)上關于這方便的東西很零散,為了便于日后回過頭來再看,于是我將這幾天的心得體會總結如下。

什么情況下會需要用java程序動態(tài)的編譯java源文件,動態(tài)的加載java類文件呢?如果很少遇到這樣的需求的兄弟們可能不會清楚動態(tài)的編譯、動態(tài)的加載用在一個什么樣的場景。下面我將我遇到的場景描述下。
Sdl說明:
為了更好的說明需求,先解釋下,我這里的sdl文件是干什么用的。

sdl文件里面主要是定義了一些遠程調(diào)用接口的相關信息,根據(jù)這些信息我們可以自己手動生成java版本的遠程調(diào)用接口。具體有些什么東西呢?比如說,接口的名稱、所在包路徑、接口參數(shù)、接口用的java bean等等。我們得到這些sdl文件后,可以利用sdl2java.exe或者sdl2java.sh工具將文件編譯成java源文件,利用這些源文件就可以進行遠程接口調(diào)用。

需求說明:
用戶只提供一個sdl文件,需要程序能夠根據(jù)這個sdl文件,提取出所有遠程調(diào)用接口,讓用戶在前端輸入?yún)?shù),然后進行遠程調(diào)用。

實現(xiàn)方案:
用戶上傳一個sdl文件到工程臨時目錄,然后程序自動的調(diào)用sdl2java.exe或者sdl2java.sh命令將sdl文件動態(tài)編譯成一系列的java源文件,然后程序動態(tài)的將這些java文件編譯成class文件,最后再動態(tài)加載到項目中。

整個實現(xiàn)方案有三個難點:

  • 用java程序調(diào)用sdl2java.exe或者sdl2java.sh命令解析sdl文件,生成一系列的java源文件
  • 動態(tài)編譯上述java源文件為class類文件
  • 動態(tài)加載class類文件



本文講解的實現(xiàn)方案的前提:
本文主要講解第二個難點如何實現(xiàn),因此假設程序已經(jīng)實現(xiàn)了將sdl文件轉換成了一系列的java文件,并存放到服務器中根目錄的temp\sdl\src目錄中

動態(tài)將java文件編譯為class文件解決方案:
將temp\sdl\src目錄中的java源文件編譯成class文件,并存放到temp\sdl\classes目錄中。

java中早就提供了用java方式去動態(tài)編譯java源文件的接口,有關java動態(tài)編譯的API都在javax.tools包中。本文主要使用jdk1.6以上版本提供的JavaCompiler工具來動態(tài)編譯java源文件。
我們可以通過ToolProvider類的靜態(tài)方法getSystemJavaCompiler得到JavaCompiler對象實例。

// 獲取編譯器實例 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();


得到JavaCompiler對象實例后,我們可以調(diào)用該工具的getTask(Writer out, JavaFileManager fileManager, DiagnosticListener<? super JavaFileObject> diagnosticListener, Iterable<String> options, Iterable<String> classes, Iterable<? extends JavaFileObject> compilationUnits) 方法獲取一個編譯任務對象。

CompilationTask compilationTask = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits);


該方法的第一個參數(shù)為文件輸出,這里我們可以不指定,我們采用javac命令的-d參數(shù)來指定class文件的生成目錄。
第二個參數(shù)為文件管理器實例

// 獲取標準文件管理器實例 StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);


該文件管理器實例的作用就是將我們需要動態(tài)編譯的java源文件轉換為getTask需要的編譯單元。

// 獲取要編譯的編譯單元 Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFileList);


第三個參數(shù)DiagnosticCollector<JavaFileObject> diagnostics是在編譯出錯時,存放編譯錯誤信息。
第四個參數(shù)為編譯命令選項,就是javac命令的可選項,這里我們主要使用了-d和-sourcepath這兩個選項。

/** * 編譯選項,在編譯java文件時,編譯程序會自動的去尋找java文件引用的其他的java源文件或者class。 -sourcepath選項就是定義java源文件的查找目錄, -classpath選項就是定義class文件的查找目錄,-d就是編譯文件的輸出目錄。 */ Iterable<String> options = Arrays.asList("-d", targetDir, "-sourcepath", sourceDir);


第五個參數(shù)為類名稱,具體作用沒研究清楚。
第六個參數(shù)為上面提到的編譯單元,就是我們需要編譯的java源文件

當我們得到CompilationTask compilationTask編譯任務后,我們就可以調(diào)用compilationTask.call()方法進行編譯工作

// 運行編譯任務 compilationTask.call()




下面代碼的運行前提條件:
首先需要將附件中的sdl.rar文件解壓到F:\亞信工作\SDL文件目錄下,sdl目錄結構見下圖



由于編譯這些java文件需要用到兩個與sdl相關的jar包,因此在運行下面的代碼前,需要將sdl.rar中l(wèi)ib目錄下的jar包導入到工程里面來。

源代碼如下,直接運行里面的main方法即可。運行后,如果輸出:編譯成功,則程序正常運行,可以通過查看sdl\classes目錄中是否有class文件檢查運行結果。

package util;import java.io.File; import java.io.FileFilter; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Arrays; import java.util.List;import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import javax.tools.JavaCompiler.CompilationTask;import org.apache.commons.lang.StringUtils;/*** @author zhengtian* * @date 2012-4-17 下午07:24:24*/ @SuppressWarnings("all") public class DynamicCompilerUtil {/*** 編譯java文件* * @param filePath* 文件或者目錄(若為目錄,自動遞歸編譯)* @param sourceDir* java源文件存放目錄* @param targetDir* 編譯后class類文件存放目錄* @param diagnostics* 存放編譯過程中的錯誤信息* @return* @throws Exception*/public static boolean compiler(String filePath, String sourceDir, String targetDir, DiagnosticCollector<JavaFileObject> diagnostics)throws Exception {// 獲取編譯器實例JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();// 獲取標準文件管理器實例StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);try {if (StringUtils.isEmpty(filePath) && StringUtils.isEmpty(sourceDir) && StringUtils.isEmpty(targetDir)) {return false;}// 得到filePath目錄下的所有java源文件File sourceFile = new File(filePath);List<File> sourceFileList = new ArrayList<File>();getSourceFiles(sourceFile, sourceFileList);// 沒有java文件,直接返回if (sourceFileList.size() == 0) {System.out.println(filePath + "目錄下查找不到任何java文件");return false;}// 獲取要編譯的編譯單元Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFileList);/*** 編譯選項,在編譯java文件時,編譯程序會自動的去尋找java文件引用的其他的java源文件或者class。 -sourcepath選項就是定義java源文件的查找目錄, -classpath選項就是定義class文件的查找目錄。*/Iterable<String> options = Arrays.asList("-d", targetDir, "-sourcepath", sourceDir);CompilationTask compilationTask = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits);// 運行編譯任務return compilationTask.call();} finally {fileManager.close();}}/*** 查找該目錄下的所有的java文件* * @param sourceFile* @param sourceFileList* @throws Exception*/private static void getSourceFiles(File sourceFile, List<File> sourceFileList) throws Exception {if (sourceFile.exists() && sourceFileList != null) {// 文件或者目錄必須存在if (sourceFile.isDirectory()) {// 若file對象為目錄// 得到該目錄下以.java結尾的文件或者目錄File[] childrenFiles = sourceFile.listFiles(new FileFilter() {public boolean accept(File pathname) {if (pathname.isDirectory()) {return true;} else {String name = pathname.getName();return name.endsWith(".java") ? true : false;}}});// 遞歸調(diào)用for (File childFile : childrenFiles) {getSourceFiles(childFile, sourceFileList);}} else {// 若file對象為文件 sourceFileList.add(sourceFile);}}}public static void main(String[] args) {try {// 編譯F:\\亞信工作\\SDL文件\\sdl\\src目錄下的所有java文件String filePath = "F:\\亞信工作\\SDL文件\\sdl\\src";String sourceDir = "F:\\亞信工作\\SDL文件\\sdl\\src";String targetDir = "F:\\亞信工作\\SDL文件\\sdl\\classes";DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();boolean compilerResult = compiler(filePath, sourceDir, targetDir, diagnostics);if (compilerResult) {System.out.println("編譯成功");} else {System.out.println("編譯失敗");for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {// System.out.format("%s[line %d column %d]-->%s%n", diagnostic.getKind(), diagnostic.getLineNumber(),// diagnostic.getColumnNumber(),// diagnostic.getMessage(null));System.out.println(diagnostic.getMessage(null));}}} catch (Exception e) {e.printStackTrace();}} }

轉自:http://www.myexception.cn/program/627493.html

?

轉載于:https://www.cnblogs.com/gisblogs/p/5504124.html

總結

以上是生活随笔為你收集整理的Java_动态加载的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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