En algunos casos, necesitamos generar el código Java dinámicamente, compilar dinámicamente y luego ejecutar el código. Javaapi proporciona herramientas correspondientes (Javacompiler) para implementar una compilación dinámica. A continuación presentamos cómo implementar la compilación dinámica del código Java a través de Javacompiler.
1. Obtén Javacompiler
Javacompiler compiler = toolProvider.getSystemJavacompiler ();
Obtenga el compilador Java proporcionado por JDK, y si no se proporciona un compilador, devuelva nulo;
2. Compilación
// Obtenga la clase de administración de archivos Java StandardJavafilemanager Manager = compiler.getStandardFilemanager (NULL, NULL, NULL); // Obtenga el iterador de objeto Java File Iterer <? extiende javaFileObject> it = ganager.getJavaFileObjects (archivos); // Establezca los parámetros de compilación ArrayList <String> OPS = new ArrayList <String> (); ops.add ("-xlint: Unchecked"); // set classpathhops. "-classpath"); Ops.add (class_path); ///////////////////////////ENen Javacompiler.compilationTask tarea = compiler.getTask (nulo, gerente, nulo, ops, null, it); // ejecutar compilación tarea tarea.call ();Cuando estamos haciendo referencia a otro código en el código fuente que queremos compilar, necesitamos establecer la ruta del código de referencia a -Classpath, de lo contrario, la compilación fallará.
Iii. Ejecución
// El nombre de clase se cargará string classname = "xxx.xxx.xxx"; // Obtener el carner de clase Loader classLoader = xxx.class.getclassloader () ;/ cargue la clase de clase <?> cls = classloader.loader.loadclass (classNameName; // llamando al método nombre de nombre Método = "Ejecuté de parámetros de parámetro <? {...}; // Obtener el método método método = cls.getDeClaredMethod (MethodName, ParamCls); // Cree el objeto de instancia de clase obj = cls.newinstance (); // objeto de parámetro de método [] params = {...}; // method method Object dente = Method.Invoke (obj, params);4. Código completo
//Classutil.javaimport java.io.filewriter; import java.io.bufferedwriter; import java.io.file; import java.io.io.ioexception; import java.util.arrayList; import javax.tools.javacompiler; import javax.tools.toolprovider; import javax.Tool.JavaolOn javax.tools.standardJavafilemanager; import org.apache.commons.logging.log; import org.apache.commons.logging.logFactory; public class ClassUtil {private estático Logger final = logFactory.getLog (classUtil.classs); Private Static Javacompiler; ToolProvider.getSystemJavaCompiler();}/** * Get the java file path* @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;}/*** Compilar archivo java* @param parámetros de compilación de ops* @param archivos compilar archivo*/private static void javac (list <string> ops, string ... archivos) {StandardJavafilemanager Manager = null; intit {Manager = CompiLer.getStandardfilemaner (NECHIMS) nulo); 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("Compile Java File:" + archivo);}} capt (excepción e) {logger.error (e);} finalmente {if (gerente! = null) {try {gerente.close ();} catch (ioexception e) {e.printstacktrace ();}}}}}/*** generar el archivo java* @param nombre de archivo* @param Code javacando* @treats @theRes @thate* @theRes @theRes @theRes @theRes compate* WriteJavAfile (archivo de cadena, String Source) lanza la excepción {if (logger.isdeBugeNabled ()) {logger.debug ("Escribir el código fuente de Java a:"+file);} bufferedwriter bw = null; intente {archivo dir = nuevo archivo (getFilePath (archivo)); if (! dir.exists ()) dir.mkdirs (); Filewriter (file)); bw.write (fuente); bw.flush ();} catch (excepción e) {throw e;} finalmente {if (bw! = Null) {bw.close ();}}}/*** cargar clase* @param nombre de clase de clase* @return*/private estatic class <?> Cargar (name de cadena) {class <?> CLESS = CLASSOLODEAD CLASSOLOG null; try {classLoLoCer = classUtil.class.getClassLoader (); cls = classLoader.LoadClass (name); if (logger.isDebugeNabled ()) {logger.debug ("cargar class ["+name+"] por"+classLoader);}} capt (excepción e) {logger.error (e);} n. Cargar clase* @param FilePath Java Code Rath* @param Fuente Código Java* @param CLSNAME Nombre de clase* @param Ops Compilar Parámetros* @return*/public static class <?> LoadClass (String filePath, string fuente, string clsname, list <string> ops) {intent {writeJavAfile (class_path+filePath, fuente); javac (ops, class_path+filePath); return load (clsname);} capt (excepción e) {logger.error (e);} return null;}/*** Método de clase de llamadas* @param Cls class* @param MethodeM Method Name* @param Parámetros de parámetros CLACLECLET @return */public static object Invoke (class <?> cls, string metodName, class <?> [] paramsCls, objeto [] params) {objeto resultado = null; try {método método = cls.getDeClaredMethod (metodName, paramsCls); obj = cls.newinstance (); result = method.inVoke (obj, params);} cett (excepción); {logger.error (e);} return resultado;}}V. 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 ("paquete combado combinado. java.text.DecimalFormat;/n "); sb.append (" suma de clase pública {/n "); sb.append (" privado final decimalFormat df = new decimalformat (//..#####/") ;/ n "); sb.append (" público doble calculado (mapa <cadena, doble> datos) {/n "); (30*data.get (/"f1/") + 20*data.get (/"f2/") + 50*data.get (/"f3/")/100;/n "); sb.append (" return double.valueOf (df.format (d);}}/n "); // Establezca el arco de parámetros de compilation <Str. String> ops = News = News = News = News = News = News = News = Newse ArrayList <String> (); ops.Add ("-xlint: Unchecked"); // Compile el código y return ClassClass <?> cls = classUtil.loadClass ("/com/incluso/test/sum.java", sb.ToString (), "com.even.test.sum", ops); // Prepare los datos de prueba <string, double, double Double Hashmap <string, double> (); data.put ("f1", 10.0); data.put ("f2", 20.0); data.put ("f3", 30.0); // Ejecutar el objeto de método de prueba resultado = classUtil.invoke (CLS, "calcular", nueva clase [] {map.class}, nuevo objeto [] {data {data});//salto de salida de salida " logger.debug (data); logger.debug ("(30*f1+20*f2+50*f3)/100 ="+resultado);}Resultados de las pruebas
16: 12: 02.860 Debug com.even.tools.classutil - Escriba el código fuente de Java a: .../classes // com/incluso/test/sum.java16: 12: 03.544 debug com.even.tools.classutil - archivo java: .../classes // com/incluso/test/sum.java16: 12: 03.545 com.even.tools.classutil - Load Class [com.even.test.sum] por Sun.misc.launcher$appclassloader@73d16e9316: 12: 03.547 Debug com.even.test.classutiltest - {f1 = 10.0, f2 = 20.0, f3 = 30.0} 16: 12: 03.547 com.even.test.classutiltest - (30*f1+20*f2+50*f3)/100 = 22.0Resumir
Lo anterior tiene que ver con los ejemplos de código de compilación y ejecución de Java Dynamic, espero que sea útil para todos. Los amigos interesados pueden continuar referiéndose a este sitio:
Programación Java Compartir código de código dinámico y cargado
Java Dynamic Programming Editar Distancia de distancia Código de ejemplo
Explicación detallada de la implementación de referencias y proxy dinámico en Java
Si hay alguna deficiencia, deje un mensaje para señalarlo. ¡Gracias amigos por su apoyo para este sitio!