java實現動態編譯並動態加載
在D盤test目錄下有個java文件:AlTest.java
public class AlTest { public String sayHello(){ System.out.println("AlTest類 sayHello()方法正在執行...."); return "hello word"; } }
現需要實現在工程已經運行過程中,進行java文件到class文件的編譯操作,並運行AlTest類的方法
package com.piao.job; import java.lang.reflect.Method; import javax.tools.JavaCompiler; import javax.tools.ToolProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component @Configurable @EnableScheduling public class CompilerJob { private static final Logger logger = LoggerFactory.getLogger(CompilerJob.class); private static boolean isExecute = false; /** * 任務:job test */ @Scheduled(cron = "*/10 * * * * * ") public void test2() { try { if (isExecute) { return; } isExecute = true; //隻是測試,所以隻執行一次 complierAndRun(); } catch (Exception e) { logger.error("test", e); } } public void complierAndRun(){ try { System.out.println(System.getProperty("user.dir")); //動態編譯 JavaCompiler javac = ToolProvider.getSystemJavaCompiler(); int status = javac.run(null, null, null, "-d", System.getProperty("user.dir")+"\\target\\classes","D:/test/AlTest.java"); if(status!=0){ System.out.println("沒有編譯成功!"); } //動態執行 Class clz = Class.forName("AlTest");//返回與帶有給定字符串名的類 或接口相關聯的 Class 對象。 Object o = clz.newInstance(); Method method = clz.getDeclaredMethod("sayHello");//返回一個 Method 對象,該對象反映此 Class 對象所表示的類或接口的指定已聲明方法 String result= (String)method.invoke(o);//靜態方法第一個參數可為null,第二個參數為實際傳參 System.out.println(result); } catch (Exception e) { logger.error("test", e); } } }
運行結果:
E:\zhoufy\small\piao-admin
AlTest類 sayHello()方法正在執行….
hello word
其中代碼:
int status = javac.run(null, null, null, “-d”, System.getProperty(“user.dir”)+”\\target\\classes”,”D:/test/AlTest.java”);
把class文件生成到瞭當前工程目錄下的classes目錄(E:\zhoufy\small\piao-admin\target\classess)所以classloader是可以加載到的,如果想知道是哪個類加載器:
Class clz = Class.forName(“AlTest”);//返回與帶有給定字符串名的類 或接口相關聯的 Class 對象。
Object o = clz.newInstance();
System.out.println(clz.getClassLoader().getSystemClassLoader());
打印的是: sun.misc.Launcher$AppClassLoader@4e0e2f2a 說明使用的是AppClassLoader
當然也可以生成到Bootstrap ClassLoader可加載的目錄下
//生成到工程classes下 //int status = javac.run(null, null, null, "-d", System.getProperty("user.dir")+"\\target\\classes","D:/test/AlTest.java"); //生成到BootStrap ClassLoader可加載目錄下 int status = javac.run(null, null, null, "-d", "C:\\Program Files\\Java\\jdk1.8.0_65\\jre\\classes","D:/test/AlTest.java");
當然也可以自定義類加載器,把文件生成在指定的外部目錄 :
public void complierAndRun(){ try { System.out.println(System.getProperty("user.dir")); //動態編譯 JavaCompiler javac = ToolProvider.getSystemJavaCompiler(); int status = javac.run(null, null, null, "-d", "D:\\","D:/test/AlTest.java"); if(status!=0){ System.out.println("沒有編譯成功!"); } //動態執行 //Class clz = Class.forName("AlTest");//返回與帶有給定字符串名的類 或接口相關聯的 Class 對象。 //自定義類加載器的加載路徑 MyClassLoader myClassLoader = new MyClassLoader("D:\\"); //包名+類名 Class clz = myClassLoader.loadClass("AlTest"); Object o = clz.newInstance(); Method method = clz.getDeclaredMethod("sayHello");//返回一個 Method 對象,該對象反映此 Class 對象所表示的類或接口的指定已聲明方法 String result= (String)method.invoke(o);//靜態方法第一個參數可為null,第二個參數為實際傳參 System.out.println(result); } catch (Exception e) { logger.error("test", e); } }
java動態執行代碼的代碼, java eval
public class ScriptUtils { private static final Logger logger = LoggerFactory.getLogger(ScriptUtils.class); /** * * <p>執行字符串計算</p> * @param express * @param params * @return * @throws ScriptException */ @SuppressWarnings("unchecked") public static <T, E> E eval(String express, Map<String, T> params) throws ScriptException{ ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("js"); if(params == null){ params = new HashMap<String,T>(); } Iterator<Map.Entry<String, T>> iter = params.entrySet().iterator(); Map.Entry<String, T> entry = null; while(iter.hasNext()){ entry = iter.next(); engine.put(entry.getKey(), entry.getValue()); } E result = null; try { result = (E)engine.eval(express); } catch (ScriptException e) { logger.warn("表達式執行異常: " + e.getMessage()); } return result; } /** * 解析字符串, 並將其當作表達式執行 * @param express * @param params * @return * @throws ScriptException */ public static <T> Boolean evalBoolean(String express, Map<String, T> params) { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("js"); if(params == null){ params = new HashMap<String,T>(); } Iterator<Map.Entry<String, T>> iter = params.entrySet().iterator(); Map.Entry<String, T> entry = null; while(iter.hasNext()){ entry = iter.next(); engine.put(entry.getKey(), entry.getValue()); } Boolean result = null; try { result = (Boolean)engine.eval(express); } catch (ScriptException e) { result = false; logger.warn("表達式執行異常: " + e.getMessage()); } return result; }
到此這篇關於java實現動態編譯並動態加載的文章就介紹到這瞭,更多相關java動態編譯內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- None Found