JBoss Fuse –一些鲜为人知的技巧

TL; DR

  1. 将Java静态调用公开为Karaf Shell本机命令
  2. 在部署时覆盖OSGi标头
  3. 在使用OSGi片段部署时间后覆盖OSGi标头

将Java静态调用公开为Karaf Shell本机命令

作为必须与支持人员和客户进行协作的软件工程师的一部分,我经常发现自己需要从无法访问的系统中提取其他信息。 通常适用于所有软件的方法通常是提取日志,调用交互式命令以获得特定的输出,或者在最复杂的情​​况下,部署一些PoC单元来验证特定行为。

JBoss Fuse和Karaf所基于的平台在公开所有这些数据方面做得非常好。

你有:

  • 大量日志并与Log4j集成
  • jmx操作的详尽列表(您最终可以使用jolokia通过http调用)
  • 大量的Shell命令

但是有时候这还不够。 如果您看过我以前有关如何在JBoss Fuse上使用Byteman的文章,则可以想象所有其他情况:

  1. 您需要打印代码中未记录或未返回的
  2. 您可能需要短路一些逻辑才能命中代码的特定执行分支
  3. 您想注入根本不存在的代码行

Byteman仍然是一个很好的选择,但是Karaf具有一种可用于运行自定义代码的工具

Karaf,允许您直接在其shell中编写代码; 并允许您将这些代码位记录为可以重新调用的宏。 这个宏看起来像一个原生的Karaf shell命令!

让我们看一个我必须实现的真实示例:

验证运行我的JBoss Fuse实例的jvm是否正在按预期解析特定的DNS。

标准JDK具有可用来解析dns名称的方法: InetAddress.gettAllByName(String)

由于该命令非常简单,这意味着它不需要复杂或结构化的输入,我想我可以将其变成易于重用的命令:

# add all public static methods on a java class as commands  to the namespace "my_context": 
# bundle 0 is because system libs are served by that bundle classloader
addcommand my_context (($.context bundle 0) loadClass java.net.InetAddress)

该时髦的行用以下方式解释:

  • addcommand是接受新命令的karaf shell功能
  • my_context是您要附加命令的名称空间/前缀。 就我而言,“ dns”将成为一个好的名称空间。 ($.context bundle 0)调用Java代码。 特别是,我们正在调用$.context实例,该实例是Karaf shell公开的内置实例,用于暴露OSGi框架,其类型为org.apache.felix.framework.BundleContextImpl ,并且正在调用其方法,称为bundle pass参数0代表负责加载JDK类的OSGi类加载器的ID。 该调用返回org.apache.felix.framework.Felix的实例,可用于加载所需的特定类定义,即java.net.InetAddress

就像内联注释所说的那样,调用addcommand公开该类上的所有公共静态方法 。 因此,现在允许我们调用这些方法,尤其是可以解析dns条目的方法:

JBossFuse:karaf@root> my_context:getAllByName "www.google.com"
www.google.com/74.125.232.146
www.google.com/74.125.232.145
www.google.com/74.125.232.148
www.google.com/74.125.232.144
www.google.com/74.125.232.147
www.google.com/2a00:1450:4002:804:0:0:0:1014

此功能在Karaf文档页面上进行了描述。

在部署时覆盖OSGi标头

如果您与Karaf合作,那么您正在使用OSGi,喜欢或讨厌它 。 每个OSGi工作流程中的一个典型步骤是播放(或战斗) OSGi标头 。 如果您完全控制项目,则这可能会或多或少容易,具体取决于部署单元之间的关系。 请参阅Christian Posta的帖子 ,以瞥见一些不明显的例子。

在这些情况下,一种非常典型的情况是必须使用捆绑包,您自己或他人的捆绑包 ,并且捆绑包头不正确 。 最终要做的通常是重新打包该捆绑包,以便您可以更改其MANIFEST的内容 ,以添加所需的OSGi标头。

Karaf在这方面具有一种设施,称为wrap协议。 您可能已经知道,这是在Karaf上部署非捆绑jar的快捷方式,但实际上不仅限于此
顾名思义,它真正要做的就是包装。 但是它可以同时包裹非捆绑包和捆绑包! 这意味着我们还可以使用它来更改我们将要安装的已打包捆绑包的元数据。

让我们举个例子,再次从现实生活中获得经验。 Apache HttpClient并非完全OSGi友好。 我们可以使用wrap:协议将其安装在Karaf上,并导出所有软件包

JBossFuse:karaf@root> install -s 'mvn:org.apache.httpcomponents/httpclient/4.2.5'
Bundle ID: 257
JBossFuse:karaf@root> exports | grep -i 257257 No active exported packages. This command only works on started bundles, use osgi:headers instead
JBossFuse:karaf@root> install -s 'wrap:mvn:org.apache.httpcomponents/httpclient/\ 4.2.5$Export-Package=*; version=4.2.5'
Bundle ID: 259
JBossFuse:karaf@root> exports | grep -i 259259 org.apache.http.client.entity; version=4.2.5259 org.apache.http.conn.scheme; version=4.2.5259 org.apache.http.conn.params; version=4.2.5259 org.apache.http.cookie.params; version=4.2.5
...

我们可以看到它也适用于普通捆绑包

JBossFuse:karaf@root> la -l | grep -i camel-core
[ 142] [Active     ] [            ] [       ] [   50] mvn:org.apache.camel/camel-core/2.12.0.redhat-610379
JBossFuse:karaf@root> install -s 'wrap:mvn:org.apache.camel/camel-core/2.12.0.redhat-610379\
$overwrite=merge&Bundle-SymbolicName=paolo-s-hack&Export-Package=*; version=1.0.1'
Bundle ID: 269JBossFuse:karaf@root> headers 269camel-core (269)
----------------
...Bundle-Vendor = Red Hat, Inc.
Bundle-Activator = org.apache.camel.impl.osgi.Activator
Bundle-Name = camel-core
Bundle-DocURL = http://redhat.com
Bundle-Description = The Core Camel Java DSL based routerBundle-SymbolicName = paolo-s-hackBundle-Version = 2.12.0.redhat-610379
Bundle-License = http://www.apache.org/licenses/LICENSE-2.0.txt
Bundle-ManifestVersion = 2...Export-Package = org.apache.camel.fabric;uses:="org.apache.camel.util,org.apache.camel.model,org.apache.camel,org.apache.camel.processor,org.apache.camel.api.management,org.apache.camel.support,org.apache.camel.spi";version=1.0.1,...

在哪里可以看到Bundle-SymbolicName并且导出的软件包版本带有我设置的值。

同样,该功能在Karaf文档中进行了描述,您可能会发现包装协议参考非常有用。

在使用OSGi片段部署时间后覆盖OSGi标头

最后一个技巧很强大,但是如果您不想冒险让一个类加载器暴露一半的类,而让另一个类加载器暴露剩余的类(那些您可能已在重写的Export添加的包),则可能需要您删除原始包。一。

实际上,有一种更好的方法来覆盖OSGi标头,它直接来自OSGi标准功能: OSGi Fragments

如果您不熟悉此概念,则直接取自OSGi Wiki的定义是:

捆绑包片段(或简称为片段)是一个捆绑包,其内容可用于另一个捆绑包(片段主机)。 重要的是,片段共享其父捆绑的类加载器。

该页面还提供了有关我将要描述的内容的进一步提示:

有时,片段用于“修补”现有的捆绑包。

我们可以使用此策略来:

  • 目标包的类路径注入.jars
  • 改变目标包的标题

我用第一种情况来修复配置错误的捆绑包,该捆绑包正在寻找一个不包含它的xml配置描述符,并且我提供了部署包含此内容的轻型Fragment Bundle。

但是我想在这里向您展示的用例是对在JBoss Fuse / Karaf上部署Byteman的方式的一种改进

如果你还记得我以前的帖子 ,因为Byteman类需要可从所有其他部署包,并可能需要提供访问每一个类,我们不得不Byteman包添加到org.osgi.framework.bootdelegation属性,指示OSGi框架通过虚拟系统捆绑包(id = 0)公开列出的软件包

您可以使用headers 0来验证当前正在使用的内容,因为它是jdk扩展和框架类的一长串,所以这里不包括输出。

如果添加我的包org.jboss.byteman.rule,org.jboss.byteman.rule.exception ,即使这些包也会在该命令的输出中列出。

该解决方案的问题在于,这是引导时间属性 。 如果要使用Byteman操作已经运行的实例的字节码,则必须在编辑此属性后重新启动它。

OSGi片段可以帮助您, 避免在引导时进行预配置。

我们可以构建一个没有实际内容的自定义空捆绑包,该捆绑包将附加到系统捆绑包并扩展其服务的包列表。

<Export-Package>org.jboss.byteman.rule,org.jboss.byteman.rule.exception
</Export-Package>
<Fragment-Host>system.bundle; extension:=framework
</Fragment-Host>

这是maven-bundle-plugin插件配置的节选,请参见此处以了解完整的Maven项目 ,尽管该项目实际上只是pom.xml 30行:

JBossFuse:karaf@root> install -s mvn:test/byteman-fragment/1.0-SNAPSHOT

一旦有了该配置,就可以使用Byteman,例如,在java.lang.String默认构造函数中插入一行。

# find your Fuse process id
PROCESS_ID=$(ps aux | grep karaf | grep -v grep | cut -d ' ' -f2)# 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 -b -Dorg.jboss.byteman.transform.all $PROCESS_ID 
# add these 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 rule, we are passing it directly inline with some bash trick
sh bmsubmit.sh /dev/stdin <<OPTS# smoke test rule that uses also a custom output file
RULE DNS StringSmokeTest
CLASS java.lang.String
METHOD <init>()
AT ENTRY
IF TRUE
DO traceln(" works: " );
traceOpen("PAOLO", "/tmp/byteman.txt");
traceln("PAOLO", " works in files too " );
traceClose("PAOLO");
ENDRULEOPTS

现在,要验证Byteman是否正常运行,我们只需在Karaf shell中调用java.lang.String构造函数即可:

JBossFuse:karaf@root> new java.lang.Stringworks:

按照我们的规则,您还将在/tmp/byteman.txt看到内容

第三个技巧的灵感来自OSGi Wiki和Spring的这个有趣的页面 。

翻译自: https://www.javacodegeeks.com/2015/02/jboss-fuse-less-known-trick.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/360739.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cocos2d-x学习笔记之图片分辨率适配

从wiki里面看到&#xff0c;新的版本是去掉了enabelRetinaDisplay&#xff0c;因为要兼容iosandroid&#xff0c;其他平台是否也是如此&#xff0c;未知&#xff5e; 测试代码 std::vector<std::string> resDirOrders; resDirOrders.push_back("testImage2"…

vue 外部方法调用内部_vue函数内部调用外部函数,报错外部函数不是函数

zeroFill (num,len,radix) {let str num.toString(radix || 10);while (str.length < len) {str 0 str;}return str;},initMap() {console.log(this.zeroFill(50, 8, 16))//底图图层数据源var googleDXSource new XYZ({tileUrlFunction: function (coor) {console.log(c…

electron+react 用户自定义安装路径

使用electron-builder打包electron项目&#xff0c;其中Windows提供了NSIS来自定义安装程序。 在主进程的package.json文件中添加一些配置 "scripts":{},"build": {"directories": {"output": "release"},"nsis":…

模型微调入门介绍一

备注&#xff1a;模型微调系列的博客部分内容来源于极客时间大模型微调训练营素材&#xff0c;撰写模型微调一系列博客&#xff0c;主要是期望把训练营的内容内化成自己的知识&#xff0c;我自己写的这一系列博客除了采纳部分训练营的内容外&#xff0c;还会扩展细化某些具体细…

JMH:如何设置和运行JMH基准

健康警告&#xff01; 这篇文章描述了如何设置和运行简单的JMH基准测试。 众所周知&#xff0c;微基准测试很难正确设置&#xff0c;即使您确实正确设置了&#xff08;通过使用JMH之类的工具&#xff09;&#xff0c;它们仍然会产生误导。 仅仅因为您的代码在极端孤立的人为情况…

npp夜光数据介绍 viirs_科研成果快报第177期:中国地区长时序AVHRR气溶胶数据的主要问题: 气溶胶反演频次与重污染天气...

中国地区长时序AVHRR气溶胶数据的主要问题&#xff1a;气溶胶反演频次与重污染天气A critical view of long-term AVHRR aerosol data record in China: Retrieval frequency and heavy pollution成果信息Minghui Tao, Rong Li, Lili Wang et al. (2020)A critical view of lon…

使用Eclipse创建一个Android程序方法

要编写Android程序&#xff0c;需要安装JDK、Eclipse和Android SDK。 Android SDK的安装路径不要在program file或program file(x86)下&#xff0c;否则在debug时会碰很奇怪的问题。最好直接放在C:\Android下。&#xff08;如果非要放在Program files下也可以&#xff0c;在ecl…

ahooks useVirtualList 滚动条抖动或者数据抖动

原因 页面内容高度发生变化引起滚动条跳动的问题。浏览器会自动触发onscroll事件&#xff0c;调整滚动条的位置&#xff0c;让滚动条不乱跳动 ; 懒加载的时候由于不断更新列表项内部的高度&#xff0c;因此就会使浏览器自动触发滚动事件&#xff0c;而滚动事件又触发懒加载的更…

如何使用Hibernate批处理DELETE语句

介绍 在我以前的文章中 &#xff0c;我解释了批处理INSERT和UPDATE语句所需的Hibernate配置。 这篇文章将继续本主题的DELETE语句批处理。 领域模型实体 我们将从以下实体模型开始&#xff1a; Post实体与Comment具有一对多关联&#xff0c;并且与PostDetails实体具有一对一…

蓝点linux_新闻速读 gt; Windows 10 的 Linux 内核将像驱动程序一样由微软更新服务进行更新 | Linux 中国...

本文字数&#xff1a;3252&#xff0c;阅读时长大约&#xff1a;4 分钟导读&#xff1a;• Ubuntu 发行商 Canonical 将参加微软欧洲虚拟开源峰会 • 树莓派支持 Vulkan 最新进展&#xff1a;通过 70000 项测试 • 谷歌浏览器开始隐藏 URL 详细路径&#xff0c;未来地址栏将只显…

struts2-通配符和动态方法调用

通配符举例--BookAction 1 public class BookAction extends ActionSupport {2 3 public String execute() throws Exception {4 System.out.println("BookAction ********** execute()");5 return null;6 }7 /*8 * 显示图书添加页…

JavaFX技巧18:路径剪切

我最近注意到&#xff0c;我致力于ControlsFX项目的PopOver控件无法正确剪切其内容。 当我为FlexCalendarFX框架开发手风琴弹出窗口时&#xff0c;这一点变得显而易见。 每当最后一个标题窗格扩展时&#xff0c;其底角不再是圆角而是正方形。 在将红色矩形作为内容放置到标题窗…

electron 微信扫码登录 ERR_PROXY_CONNECTION_FAILED

electron: Failed to load URL with error: ERR_PROXY_CONNECTION_FAILED 解决 电脑代理问题;电脑设置里面找到代理,关闭就好了

关于erlang的套接字编程

套接字编程即熟悉的Socket编程&#xff0c;根据传输层协议&#xff0c;可分为&#xff1a;UDP协议和TCP协议.下面写一个简单的例子&#xff0c;再重新认识下它&#xff1a; 1.在同一主机节点下启动两个Erlang节点. a).在第一个Erlang节点下&#xff0c;打开端口为1234的UDP套接…

kotlin 添加第一个 集合_Flutter开发必学Dart语法篇之集合操作符函数与源码分析...

简述:在上一篇文章中&#xff0c;我们全面地分析了常用集合的使用以及集合部分源码的分析。那么这一节讲点更实用的内容&#xff0c;绝对可以提高你的Flutter开发效率的函数&#xff0c;那就是集合中常用的操作符函数。这次说的内容的比较简单就是怎么用&#xff0c;以及源码内…

在Java中确定文件类型

以编程方式确定文件的类型可能非常棘手&#xff0c;并且已经提出并实现了许多基于内容的文件标识方法。 Java中有几种可用于检测文件类型的实现&#xff0c;其中大多数很大程度上或完全基于文件的扩展名。 这篇文章介绍了Java中最常见的文件类型检测实现。 本文介绍了几种在Ja…

滚动条样式设置

{scrollbar-arrow-color: red; /*上下按钮上三角箭头的颜色*/scrollbar-face-color: #CBCBCB; /*滚动条凸出部分的颜色*/scrollbar-3dlight-color: blue; /*滚动条亮边的颜色*/scrollbar-highlight-color: #333; /*滚动条空白部分的颜色*/scrollbar-shadow-color: yellow; /*滚…

程序员编程艺术第十一章:最长公共子序列(LCS)问题

程序员编程艺术第十一章&#xff1a;最长公共子序列(LCS)问题 0、前言 程序员编程艺术系列重新开始创作了&#xff08;前十章&#xff0c;请参考程序员编程艺术第一~十章集锦与总结&#xff09;。回顾之前的前十章&#xff0c;有些代码是值得商榷的&#xff0c;因当时的代码只顾…

gateway 过滤器执行顺序_Gateway网关源码解析—路由(1.1)之RouteDefinitionLocator一览...

一、概述本文主要对 路由定义定位器 RouteDefinitionLocator 做整体的认识。在 《Spring-Cloud-Gateway 源码解析 —— 网关初始化》 中&#xff0c;我们看到路由相关的组件 RouteDefinitionLocator / RouteLocator 的初始化。涉及到的类比较多&#xff0c;我们用下图重新梳理下…

JDK 8流和分组

我在JDK 8中的Stream-Powered Collections Functionality中介绍了将JDK 8的Streams与Java集合一起使用的强大功能。 我没有在那篇文章中讨论groupingBy Collector 减少操作的使用&#xff0c;因此在这篇文章中解决了分组问题。 这篇博文中的示例将演示如何将集合支持的流与gro…