Статьи

Створення динамічних додатків за допомогою javax.tools

  1. Переваги використання javax.tools
  2. Компіляція Java: принципи та реалізація
  3. Малюнок 1. Як принципи javac пов'язані з інтерфейсами пакета javax.tools
  4. Компіляція вихідного коду Java в об'єктах CharSequence
  5. JavaFileObjectImpl
  6. Лістинг 1. Клас JavaFileObjectImpl (фрагмент вихідного коду)
  7. Лістинг 2. Клас FileManagerImpl (фрагмент вихідного коду)
  8. Лістинг 3. Клас CharSequenceCompiler (фрагмент вихідного коду)
  9. Малюнок 2. Динамічне додаток, що використовує пакет javax.tools.compiler
  10. Лістинг 4. Інтерфейс Function
  11. Лістинг 5. Шаблон на основі інтерфейсу Function
  12. Лістінг 6. Метод newFunction (String expr), Який Повертає об'єкт Function
  13. Ризики і стратегії безпеки
  14. Висновок
  15. Ресурси для скачування

Вивчення і застосування класу javax.tools.JavaCompiler для побудови динамічних додатків

Пакет javax.tools, доданий в Java SE 6 як стандартний API для компіляції вихідного коду Java, дозволяє додавати динамічну функціональність для розширення статичних додатків. Ця стаття представляє огляд основних класів пакета і показує, як використовувати їх для компіляції вихідного коду Java з Java-об'єктів String, StringBuffer або CharSequence замість файлів. Потім цей фасад використовується для побудови інтерактивного додатки для побудови графіків, яке дозволяє користувачеві задати числову функцію y = f (x) за допомогою будь-якого правильного числового Java-вирази. В кінці обговорюються можливі загрози безпеки, пов'язані з динамічною компіляцією вихідного коду, і способи для усунення цих ризиків.

Ідея розширення додатків через компіляцію і завантаження Java-розширень не нова, і існує декілька каркасів, які підтримують таку функціональність. Технологія серверних Java-сторінок (JavaServer Pages - JSP) в платформі Java Enterprise Edition (Java EE) - це широко відомий приклад динамічного каркаса, які генерує і компілює Java-класи. Транслятор JSP трансформує .jsp файли в Java-сервлети (servlets), використовуючи проміжні файли вихідного коду, які потім компілюються JSP-процесором і завантажуються в Java EE-контейнер Java-сервлетов. Компіляція часто виконується прямим викликом компілятора javac, який вимагає встановленого комплекту Java-розробника (Java Development Kit - JDK), або викликом класу com.sun.tools.javac.Main, який можна знайти в JAR-архіві tools.jar від Sun. Ліцензія Sun дозволяє поширювати файл tools.jar з повною версією середовища виконання Java (Java Runtime Environment - JRE). Інші способи реалізувати подібні динамічні можливості включають в себе використання мов динамічних сценаріїв (таких як JavaScript або Groovy), які інтегруються з мовою реалізації програми (див. Розділ ресурси ) Або написання спеціального доменно-орієнтованої мови і пов'язаного з ним інтерпретатора або компілятора.

Інші середовища (такі як NetBeans та Eclipse) допускають розширення, написані безпосередньо на мові Java, але подібні системи вимагають зовнішньої статичної компіляції та управління вихідним і бінарним Java-кодом і його артефактами. Технологія Apache Commons JCI надає механізм для компіляції і завантаження Java-класів в працююче додаток. Технології Janino і Javassist також надають подібні динамічні можливості, хоча Janino обмежена конструкціями мови до версії Java 1.4, а Javassist працює не на рівні вихідного коду, а на рівні абстракції Java-класів. В розділі ресурси наведені посилання на ці проекти. Однак, оскільки Java-розробники вже звикли писати на мові Java, система, яка дозволяє просто генерувати вихідний код Java на льоту, а потім компілювати і завантажувати, обіцяє найпростіший шлях навчання і максимальну гнучкість.

Переваги використання javax.tools

Використання javax.tools надає наступні переваги:

  • Це схвалене розширення платформи Java SE, а, значить, це стандартний API, розроблений в рамках Java Community Process (JSR 199). API-інтерфейс com.sun.tools.javac.Main по специфікації не є частиною документованого API платформи Java і необов'язково є в JDK від інших постачальників; також не гарантоване наявність цього PI в майбутніх версіях Sun JDK.
  • При цьому ви використовуєте те, що знаєте: вихідний код Java, а не байт-код. Можна створювати правильні Java-класи, генеруючи відповідний вихідний код Java, без вивчення більш складних правил правильного байт-коду або нової об'єктної моделі класів, методів, оголошень і виразів.
  • Він спрощує генерацію коду і використовує один підтримуваний механізм для генерації і завантаження коду, не обмежуючи вас використанням вихідного коду на базі файлів.
  • Він переносимо між поточними і майбутніми реалізаціями JDK версії 6 і вище від різних виробників.
  • Він використовує перевірену версію компілятора Java.
  • На відміну від систем, заснованих на інтерпретації, завантажені класи можуть користуватися всіма оптимізаціями, виконуваними JRE під час виконання.

Компіляція Java: принципи та реалізація

Для розуміння пакета javax.tools корисно ознайомитися з принципами компіляції в Java і тим, як вони реалізуються в пакеті. Пакет javax.tools надає абстракції для всіх цих концепцій в загальному вигляді, що дозволяє вводити вихідний код з різних об'єктів-джерел, а не тільки з файлової системи.

Компіляція вихідного коду вимагає наступних компонентів:

  • Об'єкт (змінна) classpath (шлях до класів), через яку компілятор може знайти класи бібліотек. Об'єкт classpath для компілятора звичайно складається з упорядкованого списку каталогів файлів системи та архівних файлів (JAR або ZIP), які містять вже скомпільовані .class файли. Об'єкт classpath реалізується об'єктом типу JavaFileManager, який управляє безліч об'єктів JavaFileObject зі скомпільованими класами і вихідним кодом і об'єкта типу ClassLoader, переданим в конструктор JavaFileManager. JavaFileObject це нащадок FileObject, спеціалізований за допомогою одного з варіантів значення перераховується типу (enum) JavaFileObject.Kind, корисного може використовувати компілятор
    • SOURCE (вихідний код)
    • CLASS (скомпільований клас)
    • HTML
    • OTHER (інша)
    Кожен файл з вихідним кодом надає метод openInputStream () для доступу до вихідного коду як до об'єкта типу InputStream.
  • javac options (параметри компілятора javac), які передаються в об'єкті типу Iterable <String>
  • Source files (файли з вихідним кодом) - один або кілька вихідних .java-файлів для компіляції. Об'єкт JavaFileManager надає абстрактну файлову систему, яка прив'язує імена вихідних і одержані в результаті файлів використовують екземпляри об'єктів JavaFileObject. В даному випадку файл означає зв'язок між унікальним ім'ям і послідовністю байтів. Клієнту не обов'язково використовувати справжню файлову систему. У прикладах в статті об'єкт JavaFileManager управляє прив'язками між іменами класів і об'єктами CharSequence, що містять вихідний код Java для компіляції. Об'єкт типу JavaFileManager.Location містить ім'я файлу і прапор, який показує це місце розташування вихідного коду або місце розташування результуючого скомпільованої коду. Клас ForwardingJavaFileManager реалізує шаблон Chain of Responsibility (ланцюжок відповідальності) (див. Розділ ресурси ), Що дозволяє пов'язувати між собою менеджери, як шлях до класів (classpath) і шляхи до вихідного коду (source paths) з'єднують разом JAR-файли і каталоги. Якщо Java-клас не виявляється в першому елементі ланцюжка, пошук делегуються іншим елементам в ланцюжку.
  • Output directories (каталоги з вихідними файлами), куди компілятор записує згенеровані .class-файли. Діючи як колекція отриманих в результаті .class-файлів, об'єкт JavaFileManager також зберігає об'єкти JavaFileObject, що представляють скомпільовані CLASS-файли.
  • compiler (компілятор). Клас JavaCompiler створює об'єкти JavaCompiler.CompilationTask, які компілюють вихідний код з об'єктів JavaFileObjectSOURCE в об'єкті JavaFileManager, створюючи нові вихідні JavaFileObject CLASS файли і об'єкти типу Diagnostic (попередження і помилки). Статичний метод ToolProvider.getSystemJavaCompiler () повертає екземпляр компілятора.
  • Compiler warnings and errors (повідомлення від компілятора з попередженнями і помилками), які реалізуються класами Diagnostic і DiagnosticListener. Об'єкт типу Diagnostic - це одне попередження або помилка компіляції, видане компілятором. Об'єкт Diagnostic визначає:
    • KIND (тип): ERROR (помилка), WARNING (попередження), MANDATORY_WARNING (обов'язкове попередження), NOTE (примітка) або OTHER (інша);
    • Місцезнаходження вихідного коду (включаючи номер рядка і стовпця);
    • Повідомлення.
    Клієнт надає компілятору об'єкт типу DiagnosticListener, через який компілятор передає діагностичні повідомлення назад клієнту. Клас DiagnosticCollector - це проста реалізація DiagnosticListener.

На малюнку 1 показано зв'язок принципів компілятора javac з їх реалізацією в javax.tools:

Малюнок 1. Як принципи javac пов'язані з інтерфейсами пакета javax.tools

Вивчивши ці концепції, подивимося тепер, як з їх допомогою реалізувати фасад для компіляції об'єктів CharSequences.

Компіляція вихідного коду Java в об'єктах CharSequence

У цьому розділі буде сконструйований фасад для класу javax.tools.JavaCompiler. Клас javaxtools.compiler.CharSequenceCompiler (див. Завантаження ) Може компілювати вихідний код Java в будь-яких об'єктах java.lang.CharSequence (таких як String, StringBuffer і StringBuilder), повертаючи об'єкт типу Class. Клас CharSequenceCompiler має наступний API:

  • public CharSequenceCompiler (ClassLoader loader, Iterable <String> options): Цей конструктор приймає об'єкт типу ClassLoader, який передається компілятору Java, дозволяючи йому знаходити залежні класи. Параметр типу Iterable дозволяє клієнту передати додаткові параметри компілятора, які відповідають опцій компілятора javac.
  • public Map <String, Class <T >> compile (Map <String, CharSequence> classes, final DiagnosticCollector <JavaFileObject> diagnostics) throws CharSequenceCompilerException, ClassCastException: Це стандартний метод для компіляції, який підтримує одночасну компіляцію кількох елементів вихідного коду. Варто відзначити, що компілятор Java повинен підтримувати циклічні графи з класів, наприклад, коли A.java залежить від B.java, B.java залежить від C.java, а C.java залежить від A.java. Перший аргумент цього методу - об'єкт Map, ключі якого - повні імена класів, а відповідні їм значення - об'єкти CharSequences, що містять вихідний код цього класу. наприклад:
    • "Mypackage.A" "package mypackage; public class A {...}";
    • "Mypackage.B" "package mypackage; class B extends A implements C {...}";
    • "Mypackage.C" "package mypackage; interface C {...}"
    Компілятор додає об'єкти Diagnostics в DiagnosticCollector. Параметр типу T - це узагальнений тип, в який потрібно перетворити клас. Метод compile () перевантажується іншим методом, який приймає одне ім'я класу і об'єкт CharSequence для компіляції.
  • public ClassLoader getClassLoader (): Цей метод повертає завантажувач класів, який компілятор створив під час генерації .class-файлів, щоб з нього можна було завантажувати інші класи або ресурси.
  • public Class <T> loadClass (final String qualifiedClassName) throws ClassNotFoundException: Так метод compile () може визначити кілька класів, включаючи вкладені public-класи, цей метод дозволяє завантажити ці допоміжні класи.

Для підтримки API CharSequenceCompiler я реалізую інтерфейси пакету javax.tools з класами JavaFileObjectImpl (для зберігання об'єктів CharSequence з вихідним кодом і вихідних CLASS-об'єктів, створених компілятором) і JavaFileManagerImpl (який прив'язує імена використовують екземпляри JavaFileObjectImpl для управління послідовностями вихідного коду і байт-коду, створеного компілятором).

JavaFileObjectImpl

Клас JavaFileObjectImpl, показаний в лістингу 1 , Реалізує інтерфейс JavaFileObject і зберігає вихідний код в об'єкті CharSequence (SOURCE-об'єкти) або байт-код в об'єкті ByteArrayOutputStream (CLASS-файли). Ключовий метод - CharSequence getCharContent (final boolean ignoreEncodingErrors), через який компілятор отримує текст вихідного коду. Повний вихідний код всіх прикладів наведено в розділі Завантаження .

Лістинг 1. Клас JavaFileObjectImpl (фрагмент вихідного коду)
final class JavaFileObjectImpl extends SimpleJavaFileObject {private final CharSequence source; JavaFileObjectImpl (final String baseName, final CharSequence source) {super (CharSequenceCompiler.toURI (baseName + ".java"), Kind.SOURCE); this.source = source; } @Override public CharSequence getCharContent (final boolean ignoreEncodingErrors) throws UnsupportedOperationException {if (source == null) throw new UnsupportedOperationException ( "getCharContent ()"); return source; }}

FileManagerImpl

Клас FileManagerImpl (див. Лістинг 2) розширює клас ForwardingJavaFileManager для прив'язки повних імен класів до об'єктів JavaFileObjectImpl:

Лістинг 2. Клас FileManagerImpl (фрагмент вихідного коду)
final class FileManagerImpl extends ForwardingJavaFileManager <JavaFileManager> {private final ClassLoaderImpl classLoader; private final Map <URI, JavaFileObject> fileObjects = new HashMap <URI, JavaFileObject> (); public FileManagerImpl (JavaFileManager fileManager, ClassLoaderImpl classLoader) {super (fileManager); this.classLoader = classLoader; } @Override public FileObject getFileForInput (Location location, String packageName, String relativeName) throws IOException {FileObject o = fileObjects.get (uri (location, packageName, relativeName)); if (o! = null) return o; return super.getFileForInput (location, packageName, relativeName); } Public void putFileForInput (StandardLocation location, String packageName, String relativeName, JavaFileObject file) {fileObjects.put (uri (location, packageName, relativeName), file); }}

CharSequenceCompiler

Якщо метод не може створити об'єкт

Метод ToolProvider.getSystemJavaCompiler () може повернути null, якщо шлях до файлу tools.jar не перебуває у змінної classpath додатки. Клас CharStringCompiler виявляє цю можливу конфігураційну проблему і видає виняткову ситуацію з рекомендацією щодо усунення цієї проблеми. Варто відзначити, що ліцензія Sun дозволяє поширювати файл tools.jar разом з JRE.

Тепер з цими допоміжними класами можна визначити клас CharSequenceCompiler. Він створюється з об'єктом ClassLoader (загрузчиком класів часу виконання) і параметрами компілятора. У ньому використовується метод ToolProvider.getSystemJavaCompiler () для отримання примірника JavaCompiler, потім створюється JavaFileManagerImpl, який перенаправляється в стандартний менеджер файлів компілятора.

Метод compile () проходить за поданою на вхід таблиці ключ-значення, створюючи об'єкти JavaFileObjectImpl з кожної пари ім'я / об'єкт CharSequence і додаючи їх в JavaFileManager, щоб JavaCompiler знайшов їх при виклику методу getFileForInput () менеджера файлів. Метод compile () потім створює об'єкт JavaCompiler.Task і запускає його. Збої призводять до видачі виняткової ситуації CharSequenceCompilerException. Далі для кожного елемента вихідного коду, переданого в метод compile (), завантажується отриманий об'єкт Class і поміщається в вихідну колекцію типу Map.

Завантажувач класів, пов'язаний з CharSequenceCompiler (див. Лістинг 3), - це об'єкт типу ClassLoaderImpl, який шукає байт-код для класу в об'єкті типу JavaFileManagerImpl, повертаючи .class файли, створені компілятором:

Лістинг 3. Клас CharSequenceCompiler (фрагмент вихідного коду)
public class CharSequenceCompiler <T> {private final ClassLoaderImpl classLoader; private final JavaCompiler compiler; private final List <String> options; private DiagnosticCollector <JavaFileObject> diagnostics; private final FileManagerImpl javaFileManager; public CharSequenceCompiler (ClassLoader loader, Iterable <String> options) {compiler = ToolProvider.getSystemJavaCompiler (); if (compiler == null) {throw new IllegalStateException ( "Can not find the system Java compiler." + "Check that your class path includes tools.jar"); } ClassLoader = new ClassLoaderImpl (loader); diagnostics = new DiagnosticCollector <JavaFileObject> (); final JavaFileManager fileManager = compiler.getStandardFileManager (diagnostics, null, null); javaFileManager = new FileManagerImpl (fileManager, classLoader); this.options = new ArrayList <String> (); if (options! = null) {for (String option: options) {this.options.add (option); }}} Public synchronized Map <String, Class <T >> compile (final Map <String, CharSequence> classes, final DiagnosticCollector <JavaFileObject> diagnosticsList) throws CharSequenceCompilerException, ClassCastException {List <JavaFileObject> sources = new ArrayList <JavaFileObject> () ; for (Entry <String, CharSequence> entry: classes.entrySet ()) {String qualifiedClassName = entry.getKey (); CharSequence javaSource = entry.getValue (); if (javaSource! = null) {final int dotPos = qualifiedClassName.lastIndexOf ( '.'); final String className = dotPos == -1? qualifiedClassName: qualifiedClassName.substring (dotPos + 1); final String packageName = dotPos == -1? "": QualifiedClassName .substring (0, dotPos); final JavaFileObjectImpl source = new JavaFileObjectImpl (className, javaSource); sources.add (source); javaFileManager.putFileForInput (StandardLocation.SOURCE_PATH, packageName, className + ".java", source); }} Final CompilationTask task = compiler.getTask (null, javaFileManager, diagnostics, options, null, sources); final Boolean result = task.call (); if (result == null ||! result.booleanValue ()) {throw new CharSequenceCompilerException ( "Compilation failed.", classes.keySet (), diagnostics); } Try {Map <String, Class <T >> compiled = new HashMap <String, Class <T >> (); for (Entry <String, CharSequence> entry: classes.entrySet ()) {String qualifiedClassName = entry.getKey (); final Class <T> newClass = loadClass (qualifiedClassName); compiled.put (qualifiedClassName, newClass); } Return compiled; } Catch (ClassNotFoundException e) {throw new CharSequenceCompilerException (classes.keySet (), e, diagnostics); } Catch (IllegalArgumentException e) {throw new CharSequenceCompilerException (classes.keySet (), e, diagnostics); } Catch (SecurityException e) {throw new CharSequenceCompilerException (classes.keySet (), e, diagnostics); }}}

додаток Plotter

Тепер, коли є простий API для компіляції вихідного коду, використовуємо його для створення додатка, що будує графіки функцій і написаного за допомогою Swing. На малюнку 2 показано додаток, що малює графік функції x * sin (x) * cos (x):

Малюнок 2. Динамічне додаток, що використовує пакет javax.tools.compiler

Додаток використовує інтерфейс Function, певний в лістингу 4:

Лістинг 4. Інтерфейс Function
package javaxtools.compiler.examples.plotter; public interface Function {double f (double x); }

Додаток надає текстове поле, куди користувач може ввести вираз Java, яке повертає значення типу double, засноване на неявно оголошеному вхідному параметрі x типу double. Додаток вставляє текст цього виразу в шаблон коду, показаний в лістингу 5, в місце, позначене як $ expression. Воно також кожен раз генерує унікальне ім'я класу, замінюючи вираз $ className в шаблоні. Ім'я пакета - це також змінна в шаблоні.

Лістинг 5. Шаблон на основі інтерфейсу Function
package $ packageName; import static java.lang.Math. *; public class $ className implements javaxtools.compiler.examples.plotter.Function {public double f (double x) {return ($ expression); }}

Додаток заповнює шаблон за допомогою методу fillTemplate (packageName, className, expr), який повертає об'єкт типу String, який потім компілюється за допомогою CharSequenceCompiler. Виняткові ситуації або діагностичні повідомлення від компілятора передаються в метод log () або записуються безпосередньо в прокручуваний GUI-компонент errors у вікні програми.

Метод newFunction (), показаний в лістингу 6, повертає об'єкт, який реалізує інтерфейс Function (див. Шаблон вихідного коду в лістингу 5 ):

Лістінг 6. Метод newFunction (String expr), Який Повертає об'єкт Function
Function newFunction (final String expr) {errors.setText ( ""); try {// генерація унікальніх імен класу и пакета для забезпечення безпеки final String packageName = PACKAGE_NAME + digits (); final String className = "Fx_" + (classNameSuffix ++) + digits (); final String qName = packageName + '.' + ClassName; // генерація класу віхідного коду у виде об'єкта String final String source = fillTemplate (packageName, className, expr); // компіляція згенерованих Java-коду final DiagnosticCollector <JavaFileObject> errs = new DiagnosticCollector <JavaFileObject> (); Class <Function> compiledFunction = stringCompiler.compile (qName, source, errs, new Class <?> [] {Function.class}); log (errs); return compiledFunction.newInstance (); } Catch (CharSequenceCompilerException e) {log (e.getDiagnostics ()); } Catch (InstantiationException e) {errors.setText (e.getMessage ()); } Catch (IllegalAccessException e) {errors.setText (e.getMessage ()); } Catch (IOException e) {errors.setText (e.getMessage ()); } Return NULL_FUNCTION; }

Зазвичай доводиться генерувати класи з вихідним кодом, які розширюють відомий базовий клас або реалізують конкретний інтерфейс, так що можна перетворювати об'єкти до відомого типу і викликати їх методи через коректний API. Відзначимо, що клас Function використовувався в якості параметризрвані типу T при створенні об'єкта типу CharSequenceCompiler <T>. Це дозволяє оголосити посилання compiledFunction типу Class <Function>, а вираженню compiledFunction.newInstance () повертати об'єкт типу Function без перетворень.

Після того як був отриманий динамічно згенерований примірник Function, додаток використовує його для генерації Y-значення для діапазону X-значення, а потім виводить графік значень функції (X, Y) за допомогою JFreeChart API з відкритим кодом API (див. Розділ ресурси ). Повний лістинг Swing-додатки є в завантаження вихідному коді в пакеті javaxtools.compiler.examples.plotter.

Ця програма досить скромна потреба в генерації вихідного коду. Інші додатки можуть використовувати більш складні механізми вихідного коду, наприклад, Apache Velocity (див. Розділ ресурси ).

Ризики і стратегії безпеки

Додаток, який дозволяє користувачеві вводити довільний вихідний код Java, неминуче породжує ризики для безпеки. За аналогією з інжекцією SQL-коду (SQL injection) (див. Розділ ресурси ) Система, яка дозволяє користувачеві або іншому агенту надавати необроблений вихідний код Java для генерації байт-коду, може бути поставлена ​​під загрозу. Наприклад, в додатку Plotter, представленому в цій статті, коректне Java-вираз може містити анонімні вкладені класи, які спробують отримати доступ до системних ресурсів, запустити потоки для DOS-атаки (відмову в обслуговуванні) і виконати інші ворожі дії. Ця вразливість називається інжекцією Java-коду (Java injection). Такі додатки не можна встановлювати в небезпечні місця, де неперевірені користувачі зможуть отримати до них доступ (наприклад, в якості сервлету на Java EE-сервер або у вигляді аплету). Крім того, як правило, клієнти пакету javax.tools повинні обмежувати введення з боку користувача і транслювати запити користувача в безпечний вихідний код.

Стратегії для забезпечення безпеки при використанні цього пакета включають в себе:

  • Використання спеціальних об'єктів SecurityManager або ClassLoader, що запобігають завантаження анонімних класів або інших класів, які виходять за межі вашого безпосереднього контролю.
  • Використовувати сканер вихідного коду або інший препроцесор, щоб відкидати введені дані, що містять підозрілі конструкції коду. Наприклад, додаток Plotter може використовувати клас java.io.StreamTokenizer і відкидати введені дані, які містять символ {(ліву фігурну дужку), ефективно запобігаючи оголошення анонімних вкладених класів.
  • Використання javax.tools API, наприклад, клас JavaFileManager може відмовити в запису будь-якого непередбачуваного CLASS файлу. При компіляції конкретного класу JavaFileManager може видавати виняткову ситуацію SecurityExeception для всіх викликів при збереженні непередбачених .class файлів і допускати тільки згенеровані імена класів і пакетів, які користувач не зможе передбачити або підмінити. Ця стратегія використовується в методі newFunction додатки Plotter.

Висновок

У цій статті були розглянуті принципи і найважливіші інтерфейси пакету javax.tools, був показаний фасад для компіляції вихідного коду Java, що зберігається в об'єктах String або CharSequences, а також використання бібліотечного класу для розробки прикладу додатки, що виводить графік заданої функції f (x). Інші корисні можливості застосування цієї техніки:

  • Генерація двійкового коду читання / запису файлів з опису на мові опису даних.
  • Генерація трансляторів форматів, подібних JAXB (Java Architecture for XML Binding - Java архітектура для прив'язки до XML) або каркасів для забезпечення персистентності об'єктів (JPA, Hibernate).
  • Реалізація інтерпретаторів доменно-орієнтованих мов, що виконують трансляцію доменно-орієнтованого вихідного коду в код на мові Java, за якою слідує компіляція вихідного коду на Java і завантаження класів, як це робиться в JSP.
  • Реалізація систем, заснованих на правилах.
  • Будь-які інші мислимі застосування.

Коли у вас в наступний раз при розробці програми виникне потреба в динамічному поводженні, зверніть увагу на різноманітні і гнучкі можливості, що надаються пакетом javax.tools.

Ресурси для скачування

Схожі тими

  • Create dynamic applications with javax.tools : Оригінал статті (EN).
  • javax.tools : Документація Javadoc для API пакету.
  • JSR 199: Java Compiler API (EN): вихідний Java Specification Request, за яким був розроблений пакет javax.tools в рамках Java Community Process.
  • Apache Velocity :: процесор шаблонів, який можна використовувати для більш гнучкою і складної генерації вихідного коду Java.
  • Apache Commons JCI : Вже наявний API для забезпечення доступу до Java компілятору.
  • Janino :: Janino надає можливості схожі з пакетом javax.tools, але даний момент він обмежений сумісністю тільки з вихідним кодом Java 1.3.
  • Javassist : Javassist забезпечує динамічне створення і завантаження файлів Java-класів, але робить це через модель байт-коду, а не вихідного коду Java.
  • Java design patterns 101 (EN) (David Gallardo, developerWorks, сiчень 2002 г.): стаття, що описує шаблони Facade і Chain of Responsibility, вперше представлені в книзі Design Patterns: Elements of Reusable Object-Oriented Design (Erich Gamma et al., Addison-Wesley, 1994).
  • Call components safely (EN) (David Wheeler, developerWorks, грудень 2004 року): в цій статті розглядається інжекція SQL, вразливість в безпеці, яка дозволяє користувачам задавати звичайний текст, що вставляється потім в SQL виразу, які потім завантажуються в базу даних.
  • Invoke dynamic languages ​​dynamically (EN) (Tom McQueeney, developerWorks, вересень 2007р.): В цій серії з двох статей описується інший спосіб, за допомогою якого Java SE 6 спрощує розробку динамічної функціональності для додатків.
  • JFreeChart : API для побудови діаграм, який використовували в прикладі в статті.
  • скачайте ознайомчі версії продуктів IBM і випробуйте на практиці кошти для розробки додатків і сполучна програмне забезпечення DB2®, Lotus®, Rational®, Tivoli® і WebSphere.

Підпишіть мене на повідомлення до коментарів

LastIndexOf ( '.'); final String className = dotPos == -1?
Substring (dotPos + 1); final String packageName = dotPos == -1?
QName, source, errs, new Class <?

Новости