標籤:
實現步驟:
1.自訂一個Java類,該Java類中定義一個方法來包含需要被啟動並執行代碼。
2.動態編譯剛剛產生的Java源碼,不在磁碟上產生源碼,而是直接編譯記憶體中的Java源碼。
3.動態載入剛剛建立編譯的Java二進位碼,編譯好的Java二進位碼不是在磁碟上,而是放在記憶體中,並定義自己的類載入器,負責載入記憶體中的class檔案。
4.通過反射運行前一步載入的類。
import java.util.Arrays; import javax.tools.SimpleJavaFileObject; import javax.tools.JavaFileObject; import javax.tools.JavaCompiler; import javax.tools.ToolProvider; import javax.tools.DiagnosticCollector; import java.net.URI; /** * Description: * <br/>網站: <a href="http://www.crazyit.org" mce_href="http://www.crazyit.org">瘋狂Java聯盟</a> * <br/>Copyright (C), 2001-2010, Leeyohn * <br/>This program is protected by copyright laws. * <br/>Program Name: * <br/>Date: * @author Leeyohn [email protected] * @version 1.0 */
public class MyClassLoader extends ClassLoader { @Override public Class<?> findClass(String str) throws ClassNotFoundException { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); //用於診斷原始碼編譯錯誤的對象 DiagnosticCollector diagnostics = new DiagnosticCollector(); //記憶體中的原始碼儲存在一個從JavaFileObject繼承的類中 JavaFileObject file = new JavaSourceFromString("Temp", str.toString()); Iterable compilationUnits = Arrays.asList(file); //建立一個編譯任務 JavaCompiler.CompilationTask task = compiler.getTask(null, null, null, null, null, compilationUnits); //編譯來源程式 boolean result = task.call(); if (result) { return Class.forName("Temp"); } return null; } } class JavaSourceFromString extends SimpleJavaFileObject { private String name; private String code; public JavaSourceFromString(String name, String code) { super(URI.create("string:///" + name.replace(‘.‘, ‘/‘) + Kind.SOURCE.extension), Kind.SOURCE); this.code = code; } public CharSequence getCharContent(boolean ignoreEncodingErrors) { return code; } } |
import java.lang.reflect.Method; /** * Description: * <br/>網站: <a href="http://www.crazyit.org" mce_href="http://www.crazyit.org">瘋狂Java聯盟</a> * <br/>Copyright (C), 2001-2010, Leeyohn * <br/>This program is protected by copyright laws. * <br/>Program Name: * <br/>Date: * @author Leeyohn [email protected] * @version 1.0 */ public class Eval { public static Object eval(String str) throws Exception { StringBuffer sb = new StringBuffer(); sb.append("public class Temp"); sb.append("{"); sb.append(" public Object getObject()"); sb.append(" {"); sb.append(" " + str + "return new Object();"); sb.append(" }"); sb.append("}"); //調用自訂類載入器載入編譯在記憶體中class檔案 Class clazz = new MyClassLoader().findClass(sb.toString()); Method method = clazz.getMethod("getObject"); //通過反射調用方法 return method.invoke(clazz.newInstance()); } public static void main(String[] args) throws Exception { Object rval = eval("System.out.println(/"Hello World/");"); System.out.println(rval); } } |
Java版的實現JavaScript中的eval()函數