English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Esempio di esecuzione di codice compilato dinamicamente in Java

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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。

Ti potrebbe interessare