Статьи

Используйте Byteman в JBoss Fuse / Fabric8 / Karaf

Вы когда-нибудь оказывались в процессе, пытаясь понять, почему что-то очень простое не работает?

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

Обычно, если мне посчастливилось работать над проектом с открытым исходным кодом, я начинаю читать код . Это много раз работает; но почти всегда вы не написали этот код; и вы не очень хорошо знаете продукт. Итак, да, вы видите, какая переменная находится в контексте. Вы не имеете ни малейшего представления об их возможных значениях и, что хуже, вы не представляете, где или еще хуже, когда эти значения были созданы.

На этом этапе я обычно подключаюсь к отладчику . Я никогда не запомню параметры JVM, которые необходимы для отладки Java-процессу, но я знаю, что они где-то записаны. И современные IDE предлагают мне это, так что это не большая проблема удаленного подключения к сложному серверу приложений.

Хорошо, мы связаны. Мы можем установить точку останова недалеко от раздела, который мы считаем важным, и пройти через код. В конце концов, добавив больше brakpoint. Представление переменных IDE позволяет нам видеть значения переменных в контекстах. Мы даже можем просматривать все дерево объектов и вызывать фрагмент кода , что полезно в том случае, если простое состояние памяти объекта не дает точной информации, которая нам нужна (представьте, что вы хотите отформатировать дату или отфильтровать коллекцию).

У нас есть все инструменты, но … это медленный процесс . Каждый раз, когда я останавливаюсь на определенной точке останова, мне приходится вручную просматривать переменные. Я знаю, что мы можем улучшить ситуацию с отслеживаемыми переменными , которые находятся в верхней части окна обзора и дают вам быстрый взгляд на то, что вы уже определили как важные. Но я лично считаю, что часы имеют смысл только в том случае, если у вас очень маленький набор переменных : поскольку все они имеют одно и то же пространство имен, вы в конечном итоге получаете множество неустановленных значений, которые просто отвлекают взгляд, когда вы не находитесь в области видимости этих переменные.

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

IntelliJ и, благодаря умному трюку, даже Eclipse , позволяют добавлять операторы печати при прохождении через точку останова . Если вы комбинируете это с предотвращением приостановки точки останова , у вас есть хороший способ дополнить код, который вы отлаживаете, вызовами журнала.

Для IntelliJ проверьте здесь: http://www.jetbrains.com/idea/webhelp/enabling-disabling-and-removing-breakpoints.html

breakpointDisable1

Хотя вместо этого для Eclipse, проверьте этот трюк: http://moi.vonos.net/2013/10/adhoc-logging/ или дайте мне знать, если есть более чистый или более новый способ достичь того же результата.

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

Поэтому, ища что-то внешнее, уважаю мою IDE, я решил попробовать Byteman .

Byteman на самом деле предлагает гораздо больше, чем мне было нужно в этот раз, и это, вероятно, основная причина, по которой я решил понять, могу ли я использовать его с Fabric8.

Краткий обзор того, что делает Байтман , взят из его документации:

Byteman — это инструмент манипулирования байт-кодом, который упрощает изменение работы приложений Java либо во время загрузки, либо во время работы приложения.
Это работает без необходимости переписывать или перекомпилировать оригинальную программу.

Предложения:

  • отслеживание выполнения определенных путей кода и отображение состояния приложения или JVM
  • подрыв нормального выполнения путем изменения состояния, внеплановых вызовов методов или принудительного неожиданного возврата или выброса
  • согласование сроков действий, выполняемых независимыми потоками приложений
  • мониторинг и сбор статистики, обобщающей приложения и работу JVM

В моем конкретном случае я собираюсь использовать первое из перечисленного поведения, но вы можете легко догадаться, что все остальные аспекты могут стать полезными в какой-то момент:

  • добавить логику, чтобы предотвратить исключение NullPointerException
  • короткая схема логики, потому что вы попали в ошибку, которой нет в вашей кодовой базе, но вы все еще хотите посмотреть, что произойдет, если этой ошибки не было
  • все, что вы можете себе представить

Начать использовать Byteman обычно особенно легко . Вы даже не обязаны запускать JVM с конкретными инструкциями. Вы можете просто присоединиться к уже запущенному процессу! Это работает большую часть времени, но, к сожалению, не на Karaf с конфигурацией по умолчанию, так как это подразумевает OSGi. Но не беспокойтесь, функциональность просто простое редактирование конфигурации далеко.

Вы должны отредактировать файл:

$KARAF_HOME/etc/config.properties

и добавьте эти 2 пакета в свойство org.osgi.framework.bootdelegation :

org.jboss.byteman.rule,org.jboss.byteman.rule.exception

Это свойство используется для инструктирования платформы osgi предоставлять классы в этих пакетах из родительского загрузчика классов. См. Http://felix.apache.org/site/apache-felix-framework-configuration-properties.html.

Таким образом, вы будете избегать ClassCastException возникающего при срабатывании ваших правил Byteman.

Это в значительной степени вся дополнительная работа, которая нам понадобилась для использования Byteman в Fuse.

Вот практический пример моего взаимодействия с платформой:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# assume you have modified Fabric8's config.properties and started it and that you are using fabric8-karaf-1.2.0-SNAPSHOT
 
# find your Fabric8 process id
$ ps aux | grep karaf | grep -v grep | cut -d ' ' -f3
5200
 
# navigate to the folder where you have extracted Byteman
cd /data/software/redhat/utils/byteman/byteman-download-2.2.0.1/
# export Byteman env variable:
export BYTEMAN_HOME=$(pwd)
cd bin/
# attach Byteman to Fabric8 process, no output expected unless you enable those verbose flags
sh bminstall.sh 5200 # add this flags if you have any kind of problem and what to see what's going on: -Dorg.jboss.byteman.debug -Dorg.jboss.byteman.verbose
# install our Byteman custom rules
$ sh bmsubmit.sh ~/Desktop/RBAC_Logging.btm
install rule RBAC HanldeInvoke
install rule RBAC RequiredRoles
install rule RBAC CanBypass
install rule RBAC UserHasRole
# invoke some operation on Fabric8 to trigger our rules:
{"timestamp":1412689553,"status":200,"request":{"operation...... very long response}
 
# and now check your Fabric8 shell:
 OBJECT: io.fabric8:type=Fabric
 METHOD: containersForVersion
 ARGS: [1.0]
 CANBYPASS: false
 REQUIRED ROLES: [viewer, admin]
 CURRENT_USER_HAS_ROLE(viewer): true

Где мои правила Byteman выглядят так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
RULE RBAC HanldeInvoke
CLASS org.apache.karaf.management.KarafMBeanServerGuard
METHOD handleInvoke(ObjectName, String, Object[], String[])
AT ENTRY
IF TRUE
DO traceln(" OBJECT: " + $objectName + "
 METHOD: " + $operationName + "
 ARGS: " + java.util.Arrays.toString($params) );
ENDRULE
 
RULE RBAC RequiredRoles
CLASS org.apache.karaf.management.KarafMBeanServerGuard
METHOD getRequiredRoles(ObjectName, String, Object[], String[])
AT EXIT
IF TRUE
DO traceln(" REQUIRED ROLES: " + $! );
ENDRULE
 
RULE RBAC CanBypass
CLASS org.apache.karaf.management.KarafMBeanServerGuard
METHOD canBypassRBAC(ObjectName)
AT EXIT
IF TRUE
DO traceln(" CANBYPASS: " + $! );
ENDRULE
 
RULE RBAC UserHasRole
CLASS org.apache.karaf.management.KarafMBeanServerGuard
METHOD currentUserHasRole(String)
AT EXIT
IF TRUE
DO traceln(" CURRENT_USER_HAS_ROLE(" + $requestedRole + "): " + $! );
ENDRULE

Очевидно, это был лишь краткий пример того, что Байтман может сделать для вас. Я бы предложил вам прочитать документацию по проекту, поскольку вы можете обнаружить хорошие конструкции, которые позволят вам написать более простые правила или усовершенствовать их так, чтобы они действительно запускались только тогда, когда это важно для вас (если в моем примере вы видите некоторый шум в выводе, у вас, вероятно, есть открытый экземпляр Hawtio, который выполняет опрос, вызывая некоторые из наших установленных правил).

Отдельное спасибо Эндрю Динну, который объяснил мне, как работает Байтман, и причина моих первоначальных неудач .

Из-за моих ошибок скринкаст выглядит менее чем оптимально, но вы четко видите добавленный шум, поскольку у меня был экземпляр Hawt.io, вызывающий защищенную операцию JMX!

Ссылка: Используйте Byteman в JBoss Fuse / Fabric8 / Karaf от нашего партнера JCG Паоло Антинори в блоге Someday Never Comes .