tools jar что это
Не удалось найти tools.jar
Я строил проект на Java.
У меня есть эта ошибка:
Я установил JDK и папку: C:\Program Files\Java\jre6\lib находится в моей системе, но файл tools.jar не существует.
Да, вы загрузили и установили Java Runtime Environment (JRE) вместо Java Development Kit (JDK). У последнего есть tools.jar, java.exe, javac.exe и т.д.
Если это все еще проблема для всех, у меня есть немного разъяснений по предыдущим ответам. Я столкнулся с этой проблемой, используя ant только с установленным JDK. Хотя, установщик JDK дал мне такую структуру каталогов, как это:
Добавьте переменную системной среды под названием JAVA_HOME со значением местоположения JDK.
Перейдите в Панель управления\Система и Безопасность\Система. Расширенные системные настройки, переменные среды, системные переменные, новые… Пример:
Имя переменной: JAVA_HOME
Значение переменной: C:\Program Files\Java\jdk1.7.0_21
Закройте/снова откройте окно CMD, чтобы новая переменная вступила в силу, прежде чем пытаться повторно запустить команду ant.
У меня была та же проблема, и копирование C:\Program Files\Java\jdk1.6.0_26\lib\tools.jar в C:\Program Files\Java\jre6\lib\ext работало для меня
Если вы находитесь в Linux, вы можете решить эту проблему, установив java в систему:
Нет, согласно вашей структуре каталогов, вы установили JRE, а не JDK. Там разница.
Это должно быть что-то вроде:
Вы должны увидеть ожидаемый результат.
У меня была такая же проблема на Linux-машине. Сначала я был очень расстроен, потому что я установил JDK и JRE. Я использую версии 1.6, 1.7 и 1.8 одновременно, и я много играл с альтернативами, чтобы все было правильно настроено.
Проблема была довольно глупой для решения, но противоречащей интуиции. В то время как я использовал правильный JDK, я обратил внимание на путь инструментов jar maven, которым жаловался – он ожидал, что он будет
и это не допустимое местоположение.
который теперь разрешает
перейти к вашему пути jdk, где вы установили свой java
Например, на моем ПК JDK установлен в следующем пути
После перехода в папку lib, например, “C:\Program Files\Java\jdk1.7.0_17\lib”
в каталоге lib есть файл tool.jar
Скопируйте этот файл и пропустите его в lib forlder каталога jre7
например,
В окне eclipse > предпочтения > Java > Установленный JRE я указал каталог в каталог jre в jdk 1.7, и я работал файл для меня
например, C:\Program Files\Java\jdk1.7.0_71\jre
У вас может возникнуть аналогичная проблема на Ubuntu:
Проблема заключается в том, что JAVA_HOME установлен неправильно.
Итак, на Ubuntu 14.04 x64 с использованием Java8:
Убедитесь, что в вашу переменную PATH добавлены как% JAVA_HOME%, так и% JAVA_HOME%/bin.
Все ответы о копировании tools.jar в правильное положение в лучшем случае – плохая идея.
Убедитесь, что ваша IDE может найти эти банки так, как она была разработана и предназначена для.
он был решен со мной в windows os, установив переменную JAVA_HOME перед запуском следующим образом:
установить JAVA_HOME = C:\Program Files\Java\jdk1.8.0_111
Если вы установили JDK 9.0.1, у вас также будет эта проблема, поскольку tools.jar устарел. См. Документ миграции.
если вы установили jdk, тогда
папка должна существовать там, поэтому в режиме ожидания и дать полный путь, как
Убедитесь, что ваш путь к классам установлен правильно и указывает на правильную версию установленного JDK. Кроме того, вы используете Open JDK? У меня была эта проблема до того, как я попытался перейти от открытого JDK к Suns JDK. Это является примером того, как эта проблема может быть исправлена.
maven-compiler-plugin использует jdk, а не jre, tools.jar находится в папке C:\Program Files\Java\jdk1.6.0\lib\tools.jar
вы должны настроить проект JRE System Libary с помощью jdk, а не jar. Это самое простое решение.
Решая эту проблему, я просто скопировал файл tools.jar из C:\Program Files\Java\jre1.8.0_112\lib в C:\Program Files\Java\jdk1.8.0_112\lib, так что у меня есть два tools.jar вместо одного и проблема исчезла.
Для меня какая работа: я загрузил старую версию Java 1.7
Я фактически установил свой JAVA_HOME из C:/программных файлов X86/Java, но после установки версии 1.7 у меня была другая Java в программных файлах /Java. И в этот момент я нашел здесь tools.jar. Затем я изменил этот новый путь и работал
Я также столкнулся с той же ошибкой.
Это было удалено после установки пути Java_Home к C:\Program Files\Java\jdk1.8.0_121.
Пожалуйста, убедитесь, что bin не включен в путь, и после jdk1.8.0_121 после того, как вы определили% JAVA_HOME%\bin в переменной пути к системе, нет косой черты.
Если вы находитесь в среде RHEL, имя пакета, содержащее tools.jar, заканчивается “openjdk-devel”.
Это решение для Windows: в компьютере> Расширенные системные настройки> Дополнительно> Переменные окружения…, добавьте это в Системные переменные:
Я загрузил tools.jar, и после этого я скопировал его в путь в сообщении об ошибке.
C:\Program Files\Java\jdk-11.0.1\bin> вставьте здесь tools.jar
После этого я перезапустил Spring Tool Suit 4 и все работало. Когда я пытался исправить эту проблему, я создал новую переменную окружения: Control Panel/System/Advenced/Environmental variables/new Имя: JAVA_HOME Значение: C:\Program Files\Java\jdk-11.0.1 Но я не знаю, есть ли это необходимо.
возможно, вы обновили JRE в ОС, и добавление добавило в “путь” переменных среды запись “…/Oracle/jer”, которая перезаписывает ваш JAVA_HOME. попробуйте удалить его из “пути”, оставив JAVA_HOME.
Невозможно найти tools.jar
Я строю проект на Java.
У меня есть эта ошибка:
Я установил JDK и папка: C:\Program Files\Java\jre6\lib находится в моей системе, но файла tools.jar там нет.
Да, вы загрузили и установили Java Runtime Environment (JRE) вместо Java Development Kit (JDK). В последнем есть tools.jar, java.exe, javac.exe и т. Д.
В случае, если это все еще проблема для кого-то, у меня есть немного разъяснений относительно предыдущих ответов. Я столкнулся с этой же проблемой, используя ant с установленным JDK. Хотя установщик JDK дал мне такую структуру каталогов:
Закройте / повторно откройте окно CMD, чтобы новая переменная вступила в силу, прежде чем пытаться повторно запустить команду ant.
У меня была такая же проблема и копирование C:\Program Files\Java\jdk1.6.0_26\lib\tools.jar в C:\Program Files\Java\jre6\lib\ext работал для меня
Если вы работаете в Linux, вы можете решить эту проблему, установив Java в системе:
Нет, согласно вашей структуре каталогов, вы установили JRE, а не JDK. Есть разница
Это должно быть что-то вроде:
Вы должны увидеть ожидаемый результат.
У меня была такая же проблема на машине с Linux. Сначала я был довольно разочарован, потому что я установил JDK и JRE. Я использую версии 1.6, 1.7 и 1.8 одновременно, и я много играл с альтернативами, чтобы все было установлено правильно.
и это не является действительным местоположением.
который теперь разрешает
где tools.jar действительно проживает.
Создание самодостаточных исполняемых JAR
Когда ваше программное приложение выходит за пределы десятка строк кода, вам, вероятно, следует разделить код на несколько классов. На этом этапе встает вопрос о том, как их распределить. В Java классическим форматом является Java-архив, более известный как JAR. Но реальные программы, вероятно, зависят от других JAR.
Что такое самодостаточный JAR?
У MainClass метод static main(String… args)
Работа с classpath
Новые проблемы возникают при дистрибуции JAR, которые зависят от других JAR:
Вам необходимо синхронизировать версии библиотек.
3. По этой причине вам необходимо поместить JAR в то же место, относительное или абсолютное, в целевую файловую систему в соответствии с манифестом. Это означает, что сначала нужно открыть JAR и прочитать манифест.
Одним из способов решения этих проблем является создание уникальной единицы развертывания, которая содержит классы из всех JAR и может быть распространена как один артефакт. Существует несколько вариантов создания таких JAR:
Плагин Spring Boot (Для проектов Spring Boot)
Плагин Apache Assembly
Assembly Plugin для Apache Maven позволяет разработчикам объединять результаты проекта в единый распространяемый архив, который также содержит зависимости, модули, документацию сайта и другие файлы.
Одним из принципов Maven является создание одного артефакта на проект. Хотя бывают исключения, например, Javadoc и исходный код, но в целом, если вам нужно несколько артефактов, нужно создавать один проект на каждый артефакт. Идея плагина Assembly заключается в том, чтобы обойти это правило.
Ссылайтесь на предварительно определенную самодостаточную конфигурацию JAR
Установите главный класс для исполнения
Привяжите к package после формирование исходного JAR
Запуск mvn package дает два артефакта:
Первый JAR имеет то же содержимое, что и тот, который был бы создан без плагина. Второй — это самодостаточный JAR. Вы можете выполнить его следующим образом:
В зависимости от проекта он может выполняться успешно. или нет. Например, в примере проекта Spring Boot он не работает со следующим сообщением:
Зачастую плагин следует стратегии «побеждает последний записавший». Порядок основывается на имени JAR.
С помощью Assembly вы можете нек. Если вам нужно объединить ресурсы, вы, вероятно, захотите использовать плагин Apache Shade.
Плагин Apache Shade
Плагин Assembly является общим; плагин Shade ориентирован исключительно на задачу создания самодостаточных JAR.
Этот плагин предоставляет возможность упаковать артефакт в uber-jar, включая его зависимости, и оттенить — т.е. переименовать — пакеты некоторых зависимостей.
Плагин основан на концепции преобразователей: каждый преобразователь отвечает за работу с одним типом ресурсов. Преобразователь может копировать ресурс как есть, добавлять статическое содержимое, объединять его с другими и т.д.
Хотя вы можете разработать свой преобразователь, плагин предоставляет набор готовых преобразователей:
Конфигурация плагина Shade к приведенному выше Assembly выглядит следующим образом:
shade привязан к фазе package по умолчанию
Этот преобразователь предназначен для генерации файлов манифеста
Выполните ввод Main-Class
Настройте финальный JAR так, чтобы он был многорелизным JAR. Это необходимо в случае, когда любой из исходных JAR является многорелизным JAR
Запуск mvn package дает два артефакта:
При работе с проектом, взятым за образец, финальный исполняемый файл все еще не работает так, как ожидалось. Действительно, во время сборки появляется множество предупреждений о дублировании ресурсов. Два из них мешают корректной работе проекта. Чтобы правильно их объединить, нам нужно посмотреть на их формат:
META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat: этот Log4J2 файл содержит предварительно скомпилированные данные плагина Log4J2. Он закодирован в двоичном формате, и ни один из готовых преобразователей не может объединить такие файлы. Тем не менее, случайный поиск показывает, что кто-то уже занимался этой проблемой и выпустил преобразователь для работы с объединением.
META-INF/spring.factories : эти файлы, специфичные для Spring, они имеют формат «один ключ/много значений». Поскольку они текстовые, ни один готовый преобразователь не может корректно объединить их. Однако разработчики Spring предоставляют такую возможность (и многое другое) в своем плагине.
Чтобы настроить эти преобразователи, нам нужно добавить вышеуказанные библиотеки в качестве зависимостей к плагину Shade:
Объедините файлы /META-INF/spring.factories
Добавьте необходимый код для преобразователей
Эта конфигурация работает! Тем не менее, есть оставшиеся предупреждения:
Лицензии, предупреждения и схожие файлы
Файлы конфигурации Service Loader
Вы можете добавить и настроить дополнительные преобразователи для устранения вышеупомянутых пунктов. В целом, весь процесс требует глубокого понимания каждого вида ресурсов и знаний от том, как с ними работать.
Плагин Spring Boot
Плагин Spring Boot использует совершенно другой подход. Он не объединяет ресурсы из JAR по отдельности; он добавляет зависимые JAR по мере их появления в uber JAR. Для загрузки классов и ресурсов он предоставляет специальный механизм. Очевидно, что он предназначен для проектов Spring Boot.
Настройка плагина Spring Boot проста:
Давайте проверим структуру финального JAR:
Скомпилированные классы проекта
Загрузка классов в Spring Boot
Вот выдержка из манифеста по образцу проекта:
Как вы можете видеть, главный класс является специфичным классом Spring Boot, в то время как «настоящий» главный класс упоминается в другой записи.
Для получения дополнительной информации о структуре JAR, пожалуйста, ознакомьтесь со справочной документацией.
Заключение
В этой статье мы описали 3 различных способа создания самодостаточных исполняемых JAR:
Assembly хорошо подходит для простых проектов
Когда проект становится более сложным и вам нужно работать с дублирующимися файлами, используйте Shade
Наконец, для проектов Spring Boot лучше всего использовать специальный плагин.
Полный исходный код этой статьи можно найти на Github в формате Maven.
Материалы для дополнительного изучения:
Что такое «хороший код» — это во многом спорная тема. Кто-то скажет, что если код работает, значит он достаточно хорош. Кто-то обязательно добавит, что код должен быть легок в понимании и сопровождении. А кто-то добавит, что код еще обязательно должен быть быстрым. Об этом уже много написано и сказано. Что же, давайте еще раз поговорим на эту интересную и холиварную тему. Регистрируйтесь на онлайн-интенсив
Лучше в райнтайме, чем никогда: расширяем API JIRA «на лету»
Что делать, если имеющегося в приложении API для решения задачи недостаточно, а возможности оперативно провести изменения в код нет?
Последней надеждой в этой ситуации может быть применение средств пакета java.lang.instrument. Всем, кому интересно, что и как в Java можно сделать с кодом в уже запущенной VM, добро пожаловать под кат.
На Хабре уже есть статьи про работу с байткодом:
Задача
Итак, после двух-трех дней исследования API JIRA понимаем, что нормально реализовать кросс-валидацию значений полей(в случае когда допустимые значения одного поля зависят от значения другого поля) при создании/изменении задачи не получится никак кроме как через валидацию перехода. Подход рабочий, но сложный и не удобный, поэтому в свободное от работы время я решил продолжить исследование, чтобы иметь план Б.
На недавнем Джокере был доклад Rafael Winterhalter про библиотеку Byte Buddy, которая оборачивает мощный низкоуровневый API редактирования байт-кода в более удобную высокоуровневую оболочку. Библиотека в данный момент уже довольно популярна, в частности с недавних пор она используется в Mockito и Hibernate. Среди прочего Рафаэль рассказывал о возможности изменения с помощью Byte Buddy уже загруженных классов.
Думаем «А это мысль!», и начинаем работу.
Проектирование
Первое, из доклада Рафаэля вспомниаем, что модификация уже загруженных классов возможна только с помощью интерфейса java.lang.instrument.Instrumentation, который доступен при запуске java агента. Он может быть установлен либо при запуске VM с помощью командной строки, либо с помощью Attach API, который является платформозависимым и поставляется вместе с JDK.
Здесь есть важная деталь — удалить агент нельзя — его классы остаются загруженными до конца работы VM.
Что касается JIRA в плане поддержки attach API, то тут мы не можем гарантировать что она будет запущена на JDK и уж тем более не можем гарантировать OS, на которой она будет запущена.
Второе, вспоминаем, что основной единицей расширения функционала JIRA является add-on — Bundle на стероидах. Значит всю нашу логику, какой бы она ни была, придется оформить в виде add-on’ов. Отсюда вытекает требование, что если мы и будем вносить какие-то изменения в систему — они должны быть идемпотентными и отключаемыми.
С учетом этих ограничений видим глобально 2 задачи:
Реализация
Агент
Первым делом создаем агент:
Код тривиальный, пояснения, думаю, не нужны. Как и договаривались — максимально общая логика, вряд ли нам понадобится его часто обновлять.
Провайдер
Теперь создадим add-on, который будет этот агент аттачить в целевую VM. Начнем с логики установки агента. Полный код установщика под спойлером:
Разберем код по частям.
Самый простой сценарий — если агент уже загружен. Может, его включили через параметры командной строки при загрузке, а может, add-on устанавливается не первый раз.
Проверить — легко, достаточно загрузить класс агента системным класслоадером
Если он доступен, то больше устанавливать ничего не нужно. Но допустим у нас первая установка, и агент еще не загружен — сделаем это сами с помощью attach API. Аналогично предыдущему случаю сперва проверим — не работаем ли мы под JDK, т.е. доступен нам нужный API без дополнительных манипуляций или нет. Если нет, то попробуем «доставить» API.
Теперь рассмотрим процедуру установки attach API. Задача «превращения» JRE в JDK начинается с определения контейнерной ОС. В JIRA код определения ОС уже реализован:
Теперь, зная под какой мы ОС, рассмотрим, как можно загрузить attach API. Первым делом взглянем из чего собственно состоит attach API. Как я и говорил он — платформозависимый.
Замечание: tools.jar указан как платформонезависимый, но это не совсем так. В META-INF/services/ его скрывается конфигурационный файл com.sun.tools.attach.spi.AttachProvider, в котором перечислены доступные для окружения провайдеры:
#[solaris]sun.tools.attach.SolarisAttachProvider
#[windows]sun.tools.attach.WindowsAttachProvider
#[linux]sun.tools.attach.LinuxAttachProvider
#[macosx]sun.tools.attach.BsdAttachProvider
#[aix]sun.tools.attach.AixAttachProvider
Они, в свою, очередь как раз очень даже платформозависимы.
Чтобы подключить нужные файлы в сборку на текущий момент я решил просто вытащить файлы библиотек и копии tools.jar из соответствующих дистрибутивов JDK и сложить их в репозиторий.
Что важно отметить, так это то, что после загрузки файлы attach API нельзя удалить или изменить, поэтому если мы хотим, чтобы наш add-on по-прежнему можно было удалять и обновлять, то загружать библиотеки непосредственно из jar не надо — лучше при загрузке скопировать их из нашего jar в доступное нам из JIRA тихое, спокойное расположение.
Для копирования файлов будем использовать вот такой метод:
Кроме обычных файловых операций этот код выполняет подсчет контрольных сумм. На момент написания кода этот способ верификации необновляемых в рантайме компонентов первым пришел мне в голову. В принципе можно с тем же успехом делать проверку версии, если версионировать артефакты. Если файлы уже загружены, но контрольные суммы не совпадают с артефактами из архива, мы попытаемся их заменить.
Итак, файлы есть, давайте разберемся как загружать. Начнем с самого сложного — загрузки нативной библиотеки. Если мы заглянем в недра attach API, то увидим, что непосредственно при выполнении задач происходит выгрузка библиотеки с помощью вот такого кода:
Это говорит о том, что нам необходимо добавить расположение нашей библиотеки в «java.library.path»
После этого остается сложить нужный файл нативной библиотеки в правильный каталог ии… забить первый костыль в наше решение. «java.library.path» кэшируется в классе ClassLoader, в private static String sys_paths[]. Ну что нам private — идем сбрасывать кэш…
Вот, нативную часть мы загрузили — переходим к части API на Java. tools.jar в JDK загружается системным загрузчиком. Нам нужно добиться того же.
Немного подебажив, обнаруживаем, что системный загрузчик реализует java.net.URLClassLoader.
Если коротко, то этот загрузчик хранит расположения классов как список URL. Все, что нам нужно для загрузки — добавить URL нашего tools-[OS].jar в этот список. Изучив API URLClassLoader’а огорчаемся еще раз, т.к. обнаруживаем, что метод addURL, который делает именно то, что нужно, оказывается protected. Эх… еще одна подпорка к стройному прототипу:
Ну вот наконец-то все готово к загрузке класса виртуальной машины.
Загружать его обязательно нужно не текущим OSGi-класслоадером, а системным, который остается в системе всегда, т.к. в процессе выполнения attach этот класслоадер будет загружать нативную библиотеку, а сделать это можно только один раз. OSGi же класслоадеры создаются при установке бандла — каждый раз новый. Так что рискуем получить вот такую штуку:
… 19 more
Caused by: com.sun.tools.attach.AttachNotSupportedException: no providers installed
at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:203)
Описание не очевидное, но настоящая причина состоит в том, что мы пытаемся загрузить уже загруженную библиотеку — узнать об этом можно только продебажив attach метод и увидев настоящее исключение.
Когда мы загрузили класс, можем зарузить нужные методы и наконец-то приаттачить наш агент:
Единственной тонкостью тут является код получения pid виртуальной машины:
Способ нестандартизованный, но вполне рабочий, а в Java 9 Process API вообще позволит делать это без лиших проблем.
Add-on
Теперь встроим эту логику в add-on. Нас интересует возможность вызвать код во время установки аддона — это делается с помощью стандартного спрингового InitializingBean.
Сначала вызываем логику установки агента(рассмотренную выше), а затем открываем ServiceTracker — один из основных механизмов реализации whiteboard паттерна в OSGi. Если коротко, то эта штука позволяет нам выполнить логику при добалении/изменении сервисов определенного типа в контейнере.
Теперь, каждый раз, когда в контейнер будет регистрироваться сервис, реализующий класс InstrumentationConsumer, мы будем делать следующее
Объект java.lang.instrument.Instrumentation будем получать вот таким образом:
Переходим к написанию движка валидации.
Движок валидации
Находим точку, в которую наиболее эффективно внести изменения — класс DefaultIssueService(на самом деле далеко не все вызовы создания/изменения идут через эту точку, но это отдельная тема), и его методы:
и прикидываем какой логики нам не хватает.
Нам нужно, чтобы после вызова основной логики была вызвана кастомная валидация исходных параметров нашим кодом, которая при необходимости может изменить результат.
ByteBuddy предлагает нам 2 варианта реализации нашей задумки: с помощью прерывания и с помощью механизма Advice. Разницу подходов хорошо видно на слайде презентации Рафаэля.
Interceptor API хорошо документирован, в его качестве может выступать любой публичный класс, подробнее тут. В оригинальный байткод вызов Interceptor’а встраивается ВМЕСТО оригинального метода.
При попытке использовать этот способ я выявил 2 существенных недостатка:
Основная идея заключается в том, чтобы прервать цепочку родителей WebappClassLoader’а и вставить туда некий прокси ClassLoader, который будет пытаться загружать классы с помощью BundleClassLoader, прежде чем делегировать загрузку настоящему родителю WebappClassLoader’а
Реализация подхода вылядит так:
Применять его следует в блоке применения инструментации:
В этом случае мы сможем загружать OSGi классы через WebappClassLoader. Единственное, о чем надо позаботиться — о том, чтобы не пытаться загружать с помощью OSGi классы, загрузка которых будет делегироваться во вне OSGi, т.к. это, очевидно, приведет к зацикливанию и исключениям.
Код BundleProxyClassLoader:
Я сохранил его на случай, если кто-то захочет развить эту идею.
Второй вариант реализации инструментации — это использование Advice. Этот метод значительно хуже документирован — фактически примеры можно найти только в тикетах на Github и ответах на StackOverflow.
От первого он отличается тем, что по умолчанию наши advice-методы встраиваются в код класса. Для нас это означает:
Неожиданно нам на помощь приходит API JIRA. Каждый add-on представлен в JIRA как объект класса Plugin(обертка над Bundle с рядом специальных функций) с определенным ключом, по которому можно этот plugin искать.
Ключ задается нами в конфигурации аддона, plugin API загружается тем же класслоадером, что и наш DefaultIssueService — так что нам ничего не мешает в нашем advice’е вызвать именно наш plugin и с его помощью загрузить уже любой класс, который этим plugin’ом поставляется. Например, это может быть наш агрегатор проверок.
После этого мы можем получить экземпляр этого класса через опять-таки стандартный com.atlassian.jira.component.ComponentAccessor#getOSGiComponentInstanceOfType.
И никакой магии:
DefaultIssueServiceValidateUpdateAdvice выглядит аналогично с точностью до имен классов и методов. Пришла пора написать InstrumentationConsumer, который будет применять наш advice к нужному методу.
Тут надо сказать об одном приятном бонусе. Применение advice’а — идемпотентно! Не нужно заботиться о том, чтобы не применить трансформацию дважды при переустановке аддона — за нас это сделает VM.
Ну что ж, дело за малым — напишем агрегатор. Первым делом определяем API валидации:
Дальше стандартными средствами OSGi в момент вызова получаем все доступные валидации и выполняем их:
Все готово — собираем, уставнавливаем
Тестовая валидация
Для проверки подхода реализуем простейшую проверку:
Пытаемся создать новую задачу и вуаля!
Теперь можем удалять и ставить заново любой аддон из разработанных — поведение JIRA меняется корректно.
Заключение
Таким образом, мы получили средство динамического расширения API приложения, в данном случае JIRA. Безусловно, прежде чем использовать такой подход в production требуется тщательное тестирование, но на мой взгляд решение не окончательно закостылено, и при должной проработке такой подход может быть использован для решения «безнадежных задач» — исправление долгоживущих thirdparty дефектов, для расширения API и т.д.
Полный код самого проекта можно посмотреть на Github — пользуйтесь на здоровье!
з.ы. Чтобы не усложнять статью я не стал описывать детали сборки проекта и особенности разработки add-on’ов для JIRA — ознакомиться с этим можно здесь.