English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
In alcuni casi, dobbiamo generare dinamicamente codice Java, compilarlo dinamicamente e poi eseguire il codice. L'API JAVA fornisce gli strumenti corrispondenti (JavaCompiler) per la compilazione dinamica. Di seguito, attraverso un esempio semplice, illustreremo come utilizzare JavaCompiler per compilarne dinamicamente il codice Java.
Uno, ottenere JavaCompiler
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
Ottieni il compilatore java fornito da JDK, se non è fornito, restituisce null;
Due, compilazione
//Ottieni classe gestione file java StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null); //Ottieni iteratore oggetti java file Iterable<? extends JavaFileObject> it = manager.getJavaFileObjects(files); //Set compilation parameters ArrayList<String> ops = new ArrayList<String>(); ops.add("-Xlint:unchecked"); //Imposta classpath ops.add("-classpath"); ops.add(CLASS_PATH); //Ottieni compito compilazione JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, ops, null, it); //Esegui compito compilazione task.call();
Quando il codice sorgente da compilare si riferisce a codice esterno, è necessario impostare il percorso del codice di riferimento nel -classpath, altrimenti la compilazione fallirà.
Tre, esecuzione
//Nome classe da caricare String className = "xxx.xxx.xxx"; //Ottieni caricatore classe ClassLoader classLoader = XXX.class.getClassLoader(); //Carica classe Class<?> cls = classLoader.loadClass(className); //Nome metodo da chiamare String methodName = "execute"; //Array tipo parametri metodo Class<?>[] paramCls = {...}; //Ottieni metodo Method method = cls.getDeclaredMethod(methodName , paramCls); //Creazione istanza classe Object obj = cls.newInstance(); //Parametri metodo Object[] params = {...}; //Chiamata metodo Object result = method.invoke(obj, params);
Quattro, codice completo
//ClassUtil.java import java.io.FileWriter; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.util.ArrayList; import javax.tools.JavaCompiler; import javax.tools.ToolProvider; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class ClassUtil { private static final Log logger = LogFactory.getLog(ClassUtil.class); private static JavaCompiler compiler; static{ compiler = ToolProvider.getSystemJavaCompiler(); } /** * Ottieni il percorso del file java * @param file /* @return */ private static String getFilePath(String file){ int last1 = file.lastIndexOf('/'); int last2 = file.lastIndexOf('\'); return file.substring(0, last1 > last2 ? last1 : last2) + File.separatorChar; } /** * Compilazione dei file java /* @param ops 编译参数 * @param files File da compilare */ private static void javac(List<String> ops, String... files){ StandardJavaFileManager manager = null; try{ manager = compiler.getStandardFileManager(null, null, null); Iterable<? extends JavaFileObject> it = manager.getJavaFileObjects(files); JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, ops, null, it); task.call(); if(logger.isDebugEnabled()){ for (String file:files) logger.debug("Compila file Java: " + file); } } catch(Exception e){ logger.error(e); } finally{ if(manager!=null){ try { manager.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * Crea file java * @param file nome del file * @param source codice java * @throws Exception */ private static void writeJavaFile(String file,String source)throws Exception{ if(logger.isDebugEnabled()){ logger.debug("Scrivi codice Sorgente Java in:"+file); } BufferedWriter bw = null; try{ File dir = new File(getFilePath(file)); if(!dir.exists()) dir.mkdirs(); bw = new BufferedWriter(new FileWriter(file)); bw.write(source); bw.flush(); } catch(Exception e){ throw e; } finally{ if(bw!=null){ bw.close(); } } } /** * Carica la classe * @param name nome della classe /* @return */ private static Class<?> load(String name){ Class<?> cls = null; ClassLoader classLoader = null; try{ classLoader = ClassUtil.class.getClassLoader(); cls = classLoader.loadClass(name); if(logger.isDebugEnabled()){ logger.debug("Carica Classe["+name+"] tramite "+classLoader); } } catch(Exception e){ logger.error(e); } return cls; } /** * Compilare il codice e caricare la classe * @param filePath percorso del codice java * @param source codice java /* @param clsName 类名 /* @param ops 编译参数 /* @return */ public static Class<?> loadClass(String filePath,String source,String clsName,List<String> ops){ try { writeJavaFile(CLASS_PATH+filePath,source); javac(ops,CLASS_PATH+filePath); return load(clsName); } catch (Exception e) { logger.error(e); } return null; } /** /* 调用类方法 /* @param cls 类 /* @param methodName 方法名 /* @param paramsCls 方法参数类型 /* @param params 方法参数 /* @return */ public static Object invoke(Class<?> cls,String methodName,Class<?>[] paramsCls,Object[] params){ Object result = null; try { Method method = cls.getDeclaredMethod(methodName, paramsCls); Object obj = cls.newInstance(); result = method.invoke(obj, params); } catch (Exception e) { logger.error(e); } return result; } }
Cinque, test
public class ClassUtilTest { private static final Log logger = LogFactory.getLog(ClassUtilTest.class); public static void main(String args[]){ StringBuilder sb = new StringBuilder(); sb.append("package com.even.test;"); sb.append("import java.util.Map;\nimport java.text.DecimalFormat;\n"); sb.append("public class Sum{\n") sb.append("private final DecimalFormat df = new DecimalFormat(\"#.#####\");\n"); sb.append("public Double calculate(Map<String,Double> data){\n"); sb.append("double d = (30*data.get(\"f1\") + 20*data.get(\"f2\") + 50*data.get(\"f3\"))/100;\n"); sb.append("return Double.valueOf(df.format(d));}}\n"); //Set compilation parameters ArrayList<String> ops = new ArrayList<String>(); ops.add("-Xlint:unchecked"); //Compile code, return class Class<?> cls = ClassUtil.loadClass("/com/even/test/Sum.java",sb.toString(),"com.even.test.Sum",ops); //Prepare test data Map<String,double> data = new HashMap<String,double>(); data.put("f1", 10.0); data.put("f2", 20.0); data.put("f3", 30.0); //Execute test method Object result = ClassUtil.invoke(cls, "calculate", new Class[]{Map.class}, new Object[]{data}); //Output result logger.debug(data); logger.debug("(30*f1+20*f2+50*f3)/100 = "+result); }
Test result
16:12:02.860 DEBUG com.even.tools.ClassUtil - Write Java Source Code to: .../classes//com/even/test/Sum.java 16:12:03.544 DEBUG com.even.tools.ClassUtil - Compile Java File:.../classes//com/even/test/Sum.java 16:12:03.545 DEBUG com.even.tools.ClassUtil - Load Class[com.even.test.Sum] by sun.misc.Launcher$AppClassLoader@73d16e93 16:12:03.547 DEBUG com.even.test.ClassUtilTest - {f1=10.0, f2=20.0, f3=30.0} 16:12:03.547 DEBUG com.even.test.ClassUtilTest - (30*f1+20*f2+50*f3)/100 = 22.0
总结
以上就是本文关于Java动态编译执行代码示例的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:
java编程进行动态编译加载代码分享
Java动态规划之编辑距离问题示例代码
Java中的引用和动态代理的实现详解
如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:notice#oldtoolbag.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。