English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
В некоторых случаях нам нужно динамически генерировать код на Java, компилировать его динамически, а затем выполнять код. API Java предоставляет соответствующие инструменты (JavaCompiler) для динамической компиляции. Ниже мы через простой пример покажем, как с помощью JavaCompiler можно динамически компилировать код на Java.
Один. Получение JavaCompiler
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
Получение java компилятора, предоставляемого JDK, если компилятор не предоставлен,则在озвращает null;
Два. Компиляция
//Получение класса java.file.StandardJavaFileManager StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null); //Получение итератора объектов java.io.File Iterable<? extends JavaFileObject> it = manager.getJavaFileObjects(files); //Set compilation parameters ArrayList<String> ops = new ArrayList<String>(); ops.add("-Xlint:unchecked"); //Настройка classpath ops.add("-classpath"); ops.add(CLASS_PATH); //Получение задачи компиляции JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, ops, null, it); //Выполнение задачи компиляции task.call();
Если в исходном коде, который мы хотим компилировать, есть ссылки на другое код, мы должны установить путь к этим ссылкам в -classpath, в противном случае компиляция失败нет.
Три. Выполнение
//Имя класса для загрузки String className = "xxx.xxx.xxx"; //Получение классового загрузчика ClassLoader classLoader = XXX.class.getClassLoader(); //Загрузка класса Class<?> cls = classLoader.loadClass(className); //Название метода для вызова String methodName = "execute"; //Массив типов параметров метода Class<?>[] paramCls = {...}; //Получение метода Method method = cls.getDeclaredMethod(methodName , paramCls); //Создание экземпляра класса Object obj = cls.newInstance(); //Параметры метода Object[] params = {...}; //Вызов метода Object result = method.invoke(obj, params);
Четыре. Полный код
//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(); } /* * получить путь к 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; } /* * компилировать java файлы /* @param ops параметры компиляции * @param files файлы для компиляции */ 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("Компиляция файла Java:\n" + file); } } catch(Exception e){ logger.error(e); } finally{ if(manager!=null){ try { manager.close(); } catch (IOException e) { e.printStackTrace(); } } } } /* * Создание файла java * @param file Имя файла * @param source java код * @throws Exception */ private static void writeJavaFile(String file,String source)throws Exception{ if(logger.isDebugEnabled()){ logger.debug("Запись исходного кода Java в:\n"+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(); } } } /* * Загрузка класса * @param name Имя класса /* @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("Загрузка класса["+name+"] через "+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; } }
пятый тест
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 results logger.debug(data); logger.debug("(30*f1+20*f2+50*f3)/100 = "+result); }
Test results
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 - Компилировать Java файл:.../classes//com/even/test/Sum.java 16:12:03.545 DEBUG com.even.tools.ClassUtil - Загрузить класс [com.even.test.Sum] через 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 programming
Пример кода для задачи编辑ного расстояния в динамическом规划 Java
Подробное объяснение реализации ссылок и динамического агента в Java
Если есть недостатки, пожалуйста, оставьте комментарий. Спасибо друзьям за поддержку сайта!
Заявление: содержимое статьи предоставлено из Интернета, авторские права принадлежат соответствующему автору, материал предоставлен пользователями Интернета по собственной инициативе и загружен, сайт не имеет права собственности, не производится редактирование в ручном режиме и не несет ответственности за соответствующие юридические вопросы. Если вы обнаружите подозрительное содержание авторских прав, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (при отправке письма замените # на @) для сообщения о нарушении и предоставьте соответствующие доказательства. Если подтвердится, сайт немедленно удаляет подозрительное нарушение авторских прав.