JRebel

На Хабре несколько раз публиковались статьи, где JRebel либо просто упоминался, либо выкладывалась информация, что вышла новая версия. При этом, не всем читателям было понятно, о чём вообще речь, и как данное ПО работает.

Как непосредственному участнику разработки данного продукта, мне хотелось бы прояснить некоторые моменты, почему JRebel существует и как он может помочь Java-разработчику.

Откуда ноги растут?



Изначальная проблема известна практически любому разработчику, который работает с Java: после каких-либо изменений в проекте, для того, чтобы увидеть результат, тратится довольно много времени на сборку и развёртывание в контейнере. На Хабре уже публиковались отличные статьи о том, как можно ускорить или автоматизировать процесс разработки, не стану повторяться. Но дело в том, что в упомянутых способах есть свои изъяны: далеко не все изменения возможно перегрузить в развёрнутом приложении штатными средствами; очень легко получить утечки памяти, которые приведут к надобности перезапуска контейнера. Технические детали хорошо расписаны в серии статей в нашем сайте — любопытных приглашаю почитать.

Куда уходит время?


Как выглядит цикл разработки web-приложения, в классическом виде:
1. Сделали изменения в коде (или в ресурсах)
2. Собрали JAR/WAR/EAR
3. Развернули полученный архив в контейнере
4. Открыли развёрнутое приложение, и, после некоторых манипуляций увидели результаты своего труда.

В зависимости от размера приложения, используемого контейнера, и некоторых других факторов, этапы 2, 3 и 4 могут занимать от нескольких секунд, до совершенно невменяемых цифр. Наша компания проводила опрос разработчиков относительно используемых технологий и времени которое затрачивается на развёртывание приложения. Как оказалось, в среднем на развёртывание тратится около 3 минут за раз, и около 10 минут в час. В плачевных случаях, где на развёртывание уходит более получаса, нет даже смысла спрашивать у человека, сколько раз в час он может повторить этот процесс. Ответ очевиден.

Когда перезапуск контейнера/приложения занимает считанные секунды, проблема, описанная выше, не ощущается так сильно. Однако, по мере роста и усложнения проекта, неудобства дадут о себе знать. Тут-то и можно задуматься: может быть, JRebel — это то, что вам нужно?

JRebel в помощь!



Итак, JRebel — это инструмент, призванный избавить от проблемы повторного развёртывания приложения во время разработки, т.е. сэкономит вам много времени.

Какие приемущества появляются при использовании JRebel:
1. Поскольку JRebel умеет загружать ресурсы прямо из рабочего пространства, то отпадает надобность собирать полный архив приложения (JAR/WAR/EAR). Остаётся только скомпилировать изменённый код, что занимает гораздо меньше времени, чем полная сборка архива.
2. Не происходит повторного развёртывания приложения — снова экономим время.
3. Не создаются новые загрузчики классов (classloaders), поэтому меньше риск получить утечки памяти при обновлениях. Соответственно, экономим время на вынужденных перезапусках самого контейнера.
4. Сохраняется состояние объектов и пользовательской сессии. Поэтому, в идеале, можно оставаясь на одной и той же странице, видеть результаты изменений — лишь жми F5.

Установка и настройка


Есть несколько вариантов установки. Т.к. большинство разработчиков всё-таки работают используя IDE, такие как Eclipse, NetBeans или IntelliJ, то и естественным способом установки является установка плагина для отдельно взятого IDE.

Пользователи Eclipse, для установки, могут воспользоваться сервисом Eclipse Marketplace. Пользователи NetBeans и IntelliJIDEA могут найти JRebel в соответствующем списке плагинов. Детальные инструкции можно найти здесь. После установки плагина вам дадут знать, что неплохо бы зарегистрироваться и получить лицензию



После регистрации JRebel готов к употреблению.

На самом деле, JRebel не привязан к конкретной среде разработки, т.к. работает он не в IDE, а там, где запущено приложение — т.е. привязан к JVM процессу при помощи -javaagent аргумента, примерно так:

java -javaagent:/opt/jrebel/jrebel.jar -cp. my.awesome.Application

Конфигурация


В большинстве случаев JRebel не требует дополнительной настройки, лишь конфигурационный файл — rebel.xml — который может быть сгенерирован автоматически при помощи IDE-плагина.



Суть в том, что агент (javaagent), коим и является JRebel, должен знать, где находятся скомпилированные классы, и статические файлы (html, css, итд). Это позволит загружать все требуемые ресурсы не из развёрнутого архива, а прямо из проекта, где программист и вносит свои изменения.

Если бы все проекты следовали бы “стандартной” структуре каталогов, и компилировались бы только штатными средствами IDE, то возможно, конфигурационный файл был бы и не нужен — мы могли бы получать всю информацию о проекте из IDE или работать просто по конвенции. Но поскольку у всех разработчиков своё представление о стандартах, то и JRebel нуждается в некоторых подсказках.

Сам конфигурационный файл имеет довольно простую структуру — нужно всего лишь задать classpath и место нахождения статических ресурсов:

<?xml version="1.0" encoding="UTF-8"?>
<application
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://www.zeroturnaround.com"
  xsi:schemaLocation="http://www.zeroturnaround.com http://www.zeroturnaround.com/alderaan/rebel-2_0.xsd">
 <classpath>
    <dir name="c:\myWorkspace\myWar\target\classes"/>
    <dir name="c:\myWorkspace\myWar\src\main\resources"/>
 </classpath>
  <web>
    <link target="/">
      <dir name="c:\myWorkspace\myWar\src\main\webapp"/>
   </link>
    <link target="/jsps/">
     <dir name="c:\myWorkspace\myWar\src\main\jsps"/>
   </link>
  </web>
</application>



Как видите, при помощи такого файла, возможно отобразить любую, самую нестандартную структуру проекта — на моём опыте, такие требования возникают довольно часто. Детальное описание опций для rebel.xml можно найти в документации.

Важно! Для того чтобы JRebel мог правильно зачитать конфигурацию, rebel.xml должен быть приложен к развёртываемому приложению: для web-приложений, rebel.xml должен оказаться в WEB-INF/classes. Для JAR файлов rebel.xml должен оказаться в корне архива.



В идеальном случае в архиве может находиться только web.xml и rebel.xml, а остальные ресурсы могут быть отображены через пути в rebel.xml.

В случае Maven проектов, есть возможность использовать плагин, который умеет генерировать конфигурационный файл, и сохраняет его в правильное место.

Запуск


Из IDE запуск достаточно тривиален. В случае с IntelliJIDEA достаточно воспользоваться новой кнопкой запуска, которая появилась после установки плагина:



В Eclipse, в конфигурации запуска будет добавлена новая закладка, на которой можно отметить включен ли будет JRebel для этого запуска, и некоторые другие опции.



В случае, если хочется запускать контейнер вне среды разработки, то достаточно добавить правильный путь к jrebel.jar в параметре -javaagent в скриптах для избранного контейнера. В руководстве по конфигурации приведён список контейнеров с примерами скриптов для запуска для разных JVM и ОС.

Возможности



Кроме отображения проекта в развёрнутом приложении, что является просто удобным средством автоматизации, JRebel предлагает ещё некоторую функциональность. Прежде всего — это основная функциональность — перегрузка изменений в коде. Допустим по ходу работы наткнулись на метод, который вот руки как чешутся порефакторить. Сказано-сделано, вызываем extract method, что приводит к добавлению нового метода в класс. Стандартное средство для перегрузки кода, HotSwap, с таким изменением справиться не может. JRebel, в свою очередь, класс перегрузит и напишет об этом в консоль. Перегрузка состоится в тот момент, когда изменённый класс будет использован, тем самым симулируется ленивое поведение которое присуще Java.

Далее, предположим мы используем аннотации для настроек в рамках какого-либо фреймворка. Например, значение @RequestMapping используется для определения пути по которому будет доступен контроллер. Поменяв значение аннотации, мы ожидаем обнаружить ресурс по новому пути в нашем приложении.
Отработает это следующим образом: после компиляции, значение аннотации будет доступно в новой версии класса. Аннотации — это не исполняемый код, а некоторые мета-данные, в зависимости от которых меняет своё поведение сам фреймворк. Теперь, когда новая версия класса будет подгружена, нужно дать знать фреймворку знать, что мета-данные поменялись и стоит обновить своё поведение. Для таких случаев в JRebel необходима специальная интеграция для каждого фреймворка или контейнера.

Так же как и в случае с аннотациями, специальная интеграция требуется в случае если фреймворк опирается на внешнюю конфигурацию. Так например в случае со Spring Framework конфигурации могут задаваться как через аннотации так и через XML файлы.
К примеру, добавили новый компонент (bean) в XML конфигурации, и при помощи @Autowired аннотации хотим передать новоиспечённый компонент в контроллер.

Ограничения


Как и у всех подходов описанных на Хабре и у JRebel есть некоторые технические ограничения.

На момент написания этой статьи не поддерживается изменения иерархии классов, т.е. если в программе один класс уже описан как “A extends B” то изменить его на “A extends C” нельзя. Тоже самое относится и к изменению списка интерфейсов — нельзя добавить или удалить интерфейсы из объявления класса.

Существуют ещё некоторые моменты, которые стоит учитывать.

Статическая инициализация. JRebel старается сохранить состояние объектов, которые уже созданы в памяти. Соответственно, не происходит перезапуска конструкторов или статического блока инициализации. Из этого вытекает парочка последствий.

Изменив значение статического поля мы ожидаем увидеть это новое значение в новой версии класса. Значение это, на самом деле, будет присвоено в статическом блоке, который JRebel не перезапустил. Соответственно, нового значения мы не увидим. В данный момент JRebel перезапустит статический блок только в случае добавления нового статического поля.

Причина такого поведения в том, что происходящее в статическом блоке может неопределённым способом влиять на состояние объекта, поэтому JRebel старается перезапускать его только в самом крайнем случае.

Второе следствие, которое выходит из того, что JRebel не перезапускает конструкторы, это то, что при добавлении нового поля в класс будет присвоено значение “по умолчанию” для данного типа. Т.е. если добавить поле, тип которого не будет примитивом, то присвоенное значение будет null, что в общем случае может повлечь за собой NullPointerException, в случае если это поле будет разыменовано для существующего объекта.

JRebel SDK



Как было описано выше, для поддержки конфигураций фреймворков в JRebel требуется специальная интеграция. Мы потратили уже довольно много сил и времени для реализации всевозможных интегараций, и список поддерживаемых фреймворков довольно внушителен. При работе с некоторыми фреймворками, случается, что интеграция и не требуется и JRebel работает с ними довольно неплохо “из коробки”. За примерами ходить далеко не надо: не имея специальной интеграции для Vaadin, JRebel работает с ним довольно хорошо, и наши финские коллеги очень довольны тем, что они могут использовать JRebel с собственным фреймворком.
Таких примеров, к сожалению, не так много. Большая часть фреймворков всё таки опирается на внешнюю конфигурацию, для которой требуется дополнительная интеграция. Мы бы рады реализовать поддержку всех и вся, но успеть за всеми неизвестными фреймворками мы не можем, да и во многих фирмах создаются свои «велосипеды», кода которых мы никогда не увидим. Для таких случаев в JRebel есть возможность писать свои интеграции. У нас на сайте есть небольшое руководство о том, как можно реализовать поддержку JRebel для своих нужд.

Ресурсы



Для тех, кто заинтересовался и хочет узнать больше о продукте, и как его использовать, могу привести ссылки на некоторые ресурсы.
Создатель JavaPassion ведёт страничку, где собирает и обновляет материалы по использованию JRebel с разными контейнерами, фреймворками и IDE.
Довольно часто мы проводим тематические вебинары, на которые можно бесплатно зарегистрироваться и участвовать — в прямом эфире задать вопросы на интересующую тему.
На Vimeo существует канал JRebel, где можно найти записи вебинаров, а также и всевозможные демо-записи.

Итого



Надеюсь, после данной статьи, непосвящённым читателям стало понятнее, что такое JRebel и как его можно использовать. Если возникнут вопросы, буду рад ответить на них в комментариях.
Для тех, кто уже пользуется, и находит какие то изъяны в поведении данного ПО, не стесняйтесь написать нам на форум или обратиться в службу техподдержки, будем очень признательны.
Спасибо за внимание!
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 23
  • +2
    JRebel? Нет, не слышал.
    • +2
      Кстати, для open-source проектов и проектов на Scala можно получить бесплатную лицензию.
      • +2
        Есть ли поддержка отладки в Netbeans?
        • +1
          да. для этого нужно установить плагин plugins.netbeans.org/plugin/22254/jrebel-netbeans-plugin

          правда тут возникает вопрос, какую поддержку вы ожидаете увидеть?
          • +1
            Простейшую — чтобы сохранялся брекпойнт после сохранения файла
            • +1
              Да — эта поддержка и есть в плагине.

              Чего нехватает сейчас — в Watches не видны новые поля класса, и вероятно не будет работать Expression Evaluation. Над этим сейчас работаем.
        • +2
          А как JRebel работает с фреймворками типа Seam, где в процессе деплоя исходные классы EE-бинов заменяются различными прокси-классами?
          • +1
            JRebel умеет обновлять прокси если изначальный класс изменяется. Для Seam у JRebel есть своя интеграция, и для EE части есть интеграция практически под любой контейнер. Вот будут ли видны изменения EJB в контексте Seam — сейчас не скажу, сам не проверял. Если укажете на конкретный use-case, то будет легче проверить и при надобности допилить.
          • 0
            Оу. Цена восхитительна. $130 за год. Для сравнения: JetBrains IDEA 11 стоит 199$ (либо 99$ при апгрейде). Т.е. годовая цена плагина для IDE получается близкой к цене самой IDE. Спасибо, не нужно.
            • +1
              Для некоммерческого использования есть social.jrebel.com, который бесплатен.
              Нестоит сравнивать цены с продуктами из совершенно другой категории, JRebel стоит столько сколько стоит — аналогов нет.
              • 0
                Почему совершенно другая категория? JRebel позиционируется как продукт, ускоряющий процесс разработки. Одна из целей IDE — как раз ускорение разработки. В этом отношении, с моей субъективной точки зрения, использование хорошей IDE дает гораздо больший эффект на еденицу стоимости, чем использование JRabit.

                Что касается отсутствия аналогов. Для 90% проектов подойдет гороздо более дешевая альтернатива — докупаем планку в 2 Гб памяти за 30$, настраиваем RAM-диск и переносим туда проект с сервером. Да, редеплой будет не мгновенный, но зато он будет всегда полноценным и не будет никаких странных проблем. Как бонус, такое решение ускорит не только деплой, но работу IDE и сервера.
                • +2
                  JRabit => JRebel

                  Собственно, каждый выбирает решение по вкусу. Есть плагины которые стоят не сотни а тысячи $$$. Если мы говорим об экономии времени — IDE помогает экономить время на написании кода, JRebel экономит время на развёртывании приложения.

                  Хорошее железо это всегда хорошо, ктож спорит. Только никаким железом не поправишь суммарные часы простоя изза серверов классы WebSphere или JBoss 5.1. Ну хоть мейнфрейм поставь — не будут они быстрее запускаться и классы зачитывать.
                  • 0
                    JRabit => JRebel
                    Виноват, перепутал названия.
              • +1
                Может быть текст был неправильно истолкован — JRebel это не плагин к IDE. Это отдельный продукт, у которого, чтобы было удобно использовать есть плагины для IDE, в частности и к IDEA
                • +2
                  Я понимаю, что сам по себе JRebel — это большая серьезная и сложная разработка, тесно работающая с JVM. Но для разработчика важен только результат, а внутреннее устройство инструмента. При текущей цене JRebel подойдет только там, где все другие решения уже опробованы и клиент готов выкладывать деньги даже за небольшое дополнительное ускорение.
                  • +1
                    И то верно. Но по кактой то причине огромная доля наших пользователей используют Tomcat и не самые ужасные средства разработки. Видимо, многим наша поделка таки помогает.

                    Я понимаю весь скепсис. Но уж поверьте, текущая цена для фирм — это капля в море по сравнению с остальными расходами.
                    • +2
                      Ну, не знаю, не знаю… Сейчас даже крупные фирмы не брезгуют считать эти «капли'. Лишние две сотни на каждого разработчика в год — не так уж и мало может выходить.

                      Основная мысль которую я хотел донести — с текущей ценовой политикой JRebel скорее всего будет довольно укзонишевым продуктом. Не стоит ожидать, что он станет стандартным инструментом для большого числа разработчиков.

                      В любом случае, желаю проекту удачи! Полезный инструмент, как ни как :)
              • +2
                Цена смущает?
                Ребята из Zeroturnaround опросили большое число разработчиков во всём мире и выяснили, сколько в среднем у разработчик уходит в день на редеплой. Не помню точные цифры, но кажется, это было 10 минут в час. То есть шестая часть рабочего времени. Помножить на зарплату разработчика — получается, что JRebel окупит себя меньше чем за месяц.

                Зависит, конечно, от вашей ситуации: какая у вас архитектура, какие приложения. Иные системы не требуют редеплоя вообще (взять хотя бы Play framework), а иные редеплоятся по полчаса (говорят, в случае с WebSphere и/или Liferay люди просто вешаются). Зависит и от разработчиков: иные разработчики по-любому будут полдня пить кофе и слоняться без дела, сокращай-не сокращай время редеплоя.

                А если с разработчиками всё в порядке, то JRebel — очевидное средство для ускорения разработки. Если время сборки/редеплоя больше 10 минут, то без него просто не обойтись. Мы в своей компании стараемся строить веб-приложения максимально просто, что рестарт занимал несколько секунд, но далеко не все могут себе это позволить.
                • +1
                  Всё верно. Средняя окупаемость выходит примерно 3 недели.

                  говорят, в случае с WebSphere и/или Liferay люди просто вешаются


                  Что верно то верно.
              • 0
                Как выглядит цикл разработки web-приложения, в классическом виде:
                1. Сделали изменения в коде (или в ресурсах)
                2. Собрали JAR/WAR/EAR
                3. Развернули полученный архив в контейнере
                4. Открыли развёрнутое приложение, и, после некоторых манипуляций увидели результаты своего труда.


                Не знаю как в остальных IDE но в Eclipse возможность удаленной отладки на разных AS существует уже довольно давно. Т.е. пункты 2 и 3 лишние. Но как я понял основное преимущество JRebel в более продвинутом hot code replace. Есть ли еще какие-нибудь весомые преимущества по сравнению, скажем, с возможностями отладки в JBoss Tools?
              • +1
                В режиме отладки, как я и описывал, действительно можно возспользоваться штатными средствами обновления кода — Hotswap. Этого хватате только для того чтобы обновить тело метода, но не более. Таблице сравнения — тут.
                Это, а так же возможность обновление конфигураций фреймворков на лету — это наверное достаточно весомые приемущества.

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.