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

Ejemplo de compilación y ejecución dinámica de código en Java

En algunos casos, necesitamos generar código java dinámicamente, compilarlo dinámicamente y luego ejecutarlo. JAVAAPI proporciona las herramientas correspondientes (JavaCompiler) para realizar la compilación dinámica. A continuación, mediante un ejemplo simple, presentamos cómo realizar la compilación dinámica de código java mediante JavaCompiler.

Uno, obtener JavaCompiler

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

Obtener el compilador java proporcionado por JDK, si no se proporciona un compilador, se devuelve null;

Dos, compilar

//Obtener la clase administradora de archivos java
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
//Obtener el iterador de objetos de archivo java
Iterable<? extiende JavaFileObject> it = manager.getJavaFileObjects(archivos);
//Establecer parámetros de compilación
ArrayList<String> ops = new ArrayList<String>();
ops.add("-Xlint:unchecked");
//Establecer la clasepath
ops.add("-classpath");
ops.add(CLASS_PATH);
//Obtener la tarea de compilación
JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, ops, null, it);
//Ejecutar la tarea de compilación
task.call();

Cuando el código fuente que vamos a compilar hace referencia a otro código, necesitamos establecer la ruta del código de referencia en-de lo contrario, fallará la compilación.

Tres, ejecutar

//Nombre de la clase a cargar
String className = "xxx.xxx.xxx";
//Obtener el cargador de clases
ClassLoader classLoader = XXX.class.getClassLoader();
//Cargar clase
Class<?> cls = classLoader.loadClass(className);
//Nombre del método de llamada
String methodName = "execute";
//Tipo de array de parámetros de método
Class<?>[] paramCls = {...};
//Obtener el método
Method method = cls.getDeclaredMethod(methodName, paramCls);
//Crear una instancia de la clase
Object obj = cls.newInstance();
//Parámetros del método
Object[] params = {...};
//Llamar al método
Object result = method.invoke(obj, params);

4. Código 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();
	}
	/**
   * Obtener la ruta del archivo java
   * @param file
   * @return
   */
	private static String getFilePath(String file){
		int último1 = file.lastIndexOf("/});
		int último2 = file.lastIndexOf('\');
		devuelve file.substring(0, último1>último2?último1:último2)+File.separatorChar;
	}
	/**
   * Compilar archivos java
   * @param ops 编译参数
   * @param archivos Archivos de compilación
   */
	private static void javac(List<String> ops,String... archivos){
		StandardJavaFileManager manager = null;
		try{
			manager = compiler.getStandardFileManager(null, null, null);
			Iterable<? extiende JavaFileObject> it = manager.getJavaFileObjects(archivos);
			JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, ops, null, it);
			task.call();
			if(logger.isDebugEnabled()){
				for (String archivo:archivos)
				          logger.debug("Compilar archivo Java:") + file);
			}
		}
		catch(Exception e){
			logger.error(e);
		}
		finally{
			if(manager!=null){
				try {
					manager.close();
				}
				catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	/**
   * Generar archivo java
   * @param archivo Nombre del archivo
   * @param source java代码
   * @throws Exception
   */
	private static void escribirArchivoJava(String archivo,String contenido)throws Exception{
		if(logger.isDebugEnabled()){
			logger.debug("Escribir código fuente de Java en:")+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();
			}
		}
	}
	/**
   * Cargar clase
   * @param nombre Nombre de la clase
   * @return
   */
	private static Class<?> cargar(String nombre){
		Class<?> cls = null;
		ClassLoader classLoader = null;
		try{
			classLoader = ClassUtil.class.getClassLoader();
			cls = classLoader.loadClass(name);
			if(logger.isDebugEnabled()){
				logger.debug("Load Class["+name+"] by \+classLoader);
			}
		}
		catch(Exception e){
			logger.error(e);
		}
		return cls;
	}
	/**
   * 编译代码并加载类
   * @param filePath java代码路径
   * @param source 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;
	}
}

Cinco, prueba

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");
		//Establecer parámetros de compilación
		ArrayList<String> ops = new ArrayList<String>();
		ops.add("-Xlint:unchecked");
		//Compilar código, devolver class
		Class<?> cls = ClassUtil.loadClass("/com/even/test/Sum.java",sb.toString(),"com.even.test.Sum",ops);
		//Preparar datos de prueba
		Map<String,double> data = new HashMap<String,double>();
		data.put("f1", 10.0);
		data.put("f2", 20.0);
		data.put("f3", 30.0);
		//Ejecutar método de prueba
		Object result = ClassUtil.invoke(cls, "calculate", new Class[]{Map.class}, new Object[]{data});
		//Resultado de salida
		logger.debug(data);
		logger.debug("(30*f1+20*f2+50*f3)/100 = "+result);
	}

Resultados de la prueba

16:12:02.860 DEBUG com.even.tools.ClassUtil - Escribir código fuente de Java en: .../classes//com/even/test/Sum.java
16:12:03.544 DEBUG com.even.tools.ClassUtil - Compilar archivo de Java:.../classes//com/even/test/Sum.java
16:12:03.545 DEBUG com.even.tools.ClassUtil - Cargar Clase[com.even.test.Sum] por 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

Resumen

Este es todo el contenido del ejemplo de código de ejecución dinámica de compilación de Java en este artículo, espero que sea útil para todos. Los amigos interesados pueden continuar consultando nuestro sitio:

Compartir código de compilación dinámica y carga de código en programación Java

Ejemplo de código de problema de distancia de edición en programación dinámica de Java

Explicación detallada de la implementación de referencias y proxy dinámico en Java

¡Bienvenidos a dejar comentarios sobre lo insuficiente! Agradecemos el apoyo de los amigos a este sitio!

Declaración: El contenido de este artículo se ha obtenido de la red, es propiedad del autor original, el contenido se ha contribuido y subido por los usuarios de Internet, este sitio no posee los derechos de propiedad, no se ha realizado una edición humana y no asume la responsabilidad legal relevante. Si encuentra contenido sospechoso de infracción de derechos de autor, por favor envíe un correo electrónico a: notice#oldtoolbag.com (al enviar un correo electrónico, reemplace # con @) para denunciar y proporcionar evidencia relevante. Una vez confirmado, este sitio eliminará inmediatamente el contenido sospechoso de infracción.

Te gustaría que te gustara