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