您是否曾经尝试过了解一些非常简单的方法不起作用的过程?
您正在任何众所周知的上下文中编写代码,无论出于何种原因它都无法正常工作。 而且您信任您的平台,因此您认真阅读了所有日志。
而且,您仍然不知道为什么某些行为不符合预期。
通常,如果我有幸从事开放源代码项目,那么接下来要做的就是开始阅读代码 。 多次工作; 但是几乎总是没有编写该代码。 而且您不太了解该产品。 所以,是的,您可以看到上下文中有哪个变量。 您不知道它们可能的值 ,更糟糕的是,您不知道这些值在何处创建甚至何时创建。
此时,我通常要做的是与调试器连接。 我永远不会记住Java进程需要允许调试的JVM参数,但是我知道我已经在某个地方编写了这些参数。 而且现代IDE可以向我建议这些,因此远程连接到复杂的应用程序服务器并不是什么大麻烦。
好的,我们已连接。 我们可以在离我们认为重要的部分不远的地方放置一个断点,并逐步遍历代码。 最终增加了更多的优势。 IDE 变量视图使我们可以在上下文中查看变量的值。 我们甚至可以浏览整个对象树并调用代码片段,以防对象的普通内存状态无法真正提供所需的准确信息(假设您要格式化Date或过滤集合)。
我们拥有所有工具,但是……这是一个缓慢的过程 。 每次我在特定的断点处停止时,都必须手动浏览变量。 我知道,我们可以通过监视变量来改善这种情况,这些变量始终位于概述窗口的顶部,并让您快速查看已确定的重要内容。 但是我个人发现, 只有在变量很少的情况下 ,监视才有意义 :由于它们都共享相同的名称空间,因此当您不在一个范围内时,会看到许多未设置的值,这只会分散您的视线变量。
我最近学到了一种技巧,可以改善与您共享的这些工作流程,以防您不了解:
IntelliJ ,甚至是Eclipse ,都具有巧妙的技巧,使您可以在通过断点时添加打印语句 。 如果将其与防止断点暂停结合起来,则有一种不错的方法,可以通过日志调用来扩展正在调试的代码。
对于IntelliJ,请在此处检查:http://www.jetbrains.com/idea/webhelp/enabling-disabling-and-removing-breakpoints.html
而对于Eclipse而言,请检查以下技巧:http://moi.vonos.net/2013/10/adhoc-logging/或让我知道是否有更清洁或更新颖的方法来达到相同的结果。
上面的技巧有效。 但是它的主要缺点是您正在向工作空间添加本地配置 。 您不能轻易与他人分享此内容。 您可能希望将工作空间重新用于其他会话,并且看到所有这些日志条目或断点会分散您的注意力 。
因此,在寻求IDE的外部支持时,我决定尝试Byteman 。
Byteman实际上提供的功能远远超出我这次所需的功能,这可能是我决定了解是否可以在Fabric8中使用它的主要原因。
快速回顾一下Byteman的工作,直接摘自其文档:
Byteman是一个字节码操作工具,它使在加载时或应用程序运行时更改Java应用程序的操作变得简单。
它可以工作,而无需重写或重新编译原始程序。提供:
- 跟踪特定代码路径的执行并显示应用程序或JVM状态
- 通过更改状态,进行计划外的方法调用或强制意外返回或抛出来破坏正常执行
- 安排由独立应用程序线程执行的活动的时间安排
- 监视和收集汇总应用程序和JVM操作的统计信息
在我的特定情况下,我将使用列出的行为中的第一个,但是您可以很容易地猜到所有其他方面可能会在某个时候变得很方便:
- 添加一些逻辑来防止
NullPointerException
- 短路一些逻辑,因为您遇到的错误不在代码库中,但您仍然想看看如果不存在该错误会发生什么
- 您可以想象的其他任何事情……
开始使用Byteman通常特别容易 。 您甚至没有被迫使用特定的指令来启动您的jvm。 您可以只附加到已经运行的进程! 这在大多数情况下都有效,但是不幸的是,由于OSGi的影响,在默认配置下不适用于Karaf。 但不用担心,该功能仅是简单的配置编辑 。
您必须编辑文件:
$KARAF_HOME/etc/config.properties
并添加此2包到proprerty org.osgi.framework.bootdelegation
:
org.jboss.byteman.rule,org.jboss.byteman.rule.exception
该属性用于指示osgi框架从父Classloader的那些包中提供类。 参见http://felix.apache.org/site/apache-felix-framework-configuration-properties.html
这样,您将避免在触发Byteman规则时引发ClassCastException
。
这几乎是我们在Fuse上使用Byteman所需的所有额外工作。
这是我与平台互动的实际示例 :
# 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:
$ curl -u admin:admin 'http://localhost:8181/jolokia/exec/io.fabric8:type=Fabric/containersForVersion(java.lang.String)/1.0'
{"timestamp":1412689553,"status":200,"request":{"operation...... very long response}# and now check your Fabric8 shell:OBJECT: io.fabric8:type=FabricMETHOD: containersForVersionARGS: [1.0]CANBYPASS: falseREQUIRED ROLES: [viewer, admin]CURRENT_USER_HAS_ROLE(viewer): true
我的Byteman规则如下:
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) );
ENDRULERULE RBAC RequiredRoles
CLASS org.apache.karaf.management.KarafMBeanServerGuard
METHOD getRequiredRoles(ObjectName, String, Object[], String[])
AT EXIT
IF TRUE
DO traceln(" REQUIRED ROLES: " + $! );
ENDRULERULE RBAC CanBypass
CLASS org.apache.karaf.management.KarafMBeanServerGuard
METHOD canBypassRBAC(ObjectName)
AT EXIT
IF TRUE
DO traceln(" CANBYPASS: " + $! );
ENDRULERULE RBAC UserHasRole
CLASS org.apache.karaf.management.KarafMBeanServerGuard
METHOD currentUserHasRole(String)
AT EXIT
IF TRUE
DO traceln(" CURRENT_USER_HAS_ROLE(" + $requestedRole + "): " + $! );
ENDRULE
显然,这只是Byteman可以为您提供服务的简短示例。 我邀请您阅读项目文档,因为您可能会发现不错的结构 ,这些结构可以使您编写更简单的规则或对其进行完善以仅在与您相关的情况下才真正触发(如果在我的示例中,您在输出中看到一些噪音,您可能会打开一个正在执行轮询的Hawtio实例,从而触发了一些已安装的规则)。
特别感谢Andrew Dinn向我解释了Byteman的工作方式和最初失败的原因。
由于我的错误,截屏视频不是最佳选择,但是由于我有一个Hawt.io实例调用受保护的JMX操作,因此您清楚地看到了增加的噪音!
翻译自: https://www.javacodegeeks.com/2014/10/use-byteman-in-jboss-fuse-fabric8-karaf.html