3、【java程序运行监控byteman】Byteman脚本详解及javaagent和byteman结合使用详细示例

java程序运行监控byteman 系列文章

1、【java程序运行监控byteman】之安装部署和入门示例
2、【java程序运行监控byteman】使用示例(运行中方法耗时监控、javaagent监控、jvm监控、规则的检查、是否运行以及查看等)
3、【java程序运行监控byteman】Byteman脚本详解及javaagent和byteman结合使用详细示例



本文简单的介绍了byteman脚本编写及示例、javaagent和byteman结合三种情况使用详细示例。
本文分为2个部分,及byteman的脚本介绍、javaagent与byteman结合使用。

一、Byteman脚本介绍

官网地址:https://github.com/bytemanproject/byteman

1、脚本结构

1)、脚本示例

RULE example rule
# comment line in rule body
. . .
ENDRULE

2)、脚本说明

RULE <rule name>
CLASS <class name>
METHOD <method name>
BIND <bindings>
IF  <condition>
DO  <actions>
ENDRULE

全部的合法定位点或者说注入点,更多的信息参考官方文档说明

AT ENTRY
AT EXIT
AT LINE number
AT READ [type .] field [count | ALL ]
AT READ $var-or-idx [count | ALL ]
AFTER READ [ type .] field [count | ALL ]
AFTER READ $var-or-idx [count | ALL ]
AT WRITE [ type .] field [count | ALL ]
AT WRITE $var-or-idx [count | ALL ]
AFTER WRITE [ type .] field [count | ALL ]
AFTER WRITE $var-or-idx [count | ALL ]
AT INVOKE [ type .] method [ ( argtypes ) ] [count | ALL ]
AFTER INVOKE [ type .] method [ ( argtypes ) ][count | ALL ]
AT SYNCHRONIZE [count | ALL ]
AFTER SYNCHRONIZE [count | ALL ]
AT THROW [count | ALL ]
AT EXCEPTION EXIT

2、自定义规则

1)、自定义规则源码

class HelperSub extends Helper {
  public boolean debug(String message) {
      super("!!! IMPORTANT EVENT !!! " + message);
  }
}

本示例中的子规则是继承制org.jboss.byteman.rule.helper.Helper

2)、规则示例

RULE help yourself but rely on others
CLASS com.arjuna.wst11.messaging.engines.CoordinatorEngine
METHOD commit
HELPER HelperSub
AT ENTRY
IF NOT flagged($this)
DO debug("throwing wrong state");
 flag($this);
 throw new WrongStateException()
ENDRULE

3、Byteman环境变量

在Byteman中,环境变量有如下这些,如果了解更多的信息则参考官方文档。

  • org.jboss.byteman.compileToBytecode
  • org.jboss.byteman.dump.generated.classes
  • org.jboss.byteman.dump.generated.classes.directory
  • org.jboss.byteman.dump.generated.classes.intermediate
  • org.jboss.byteman.verbose 如果设置将显示执行的各种跟踪信息到System.out,包括类型检查,编译,和执行规则
  • org.jboss.byteman.debug
  • org.jboss.byteman.transform.all 如果设置了将允许注入java.lang和其子包的class
  • org.jboss.byteman.skip.overriding.rules
  • org.jboss.byteman.allow.config.updates
  • org.jboss.byteman.sysprops.strict

4、Byteman其它命令

在解压的Byteman的bin目录下,有非常多的脚本(更多脚本参考官方文档),简单介绍如下所示:

  • bmcheck 在注入规则文件之前,该命令可以在线下对你的规则脚本进行解析和类型检查
  • bminstall 安装agent到一个正在运行的程序中
  • bmjava 该脚本包装了-javaagent选项。它的用法很像java命令,但是它能以-javaagent script:选项的方式接受Byteman规则脚本。并且自动以boot:的方式绑定了Byteman的Jar文件
  • bmsetenv 该脚本用来设置环境,agent对配置其行为的各种环境设置非常敏感
  • bmsubmit 提交和卸载规则脚本

二、javaagent与byteman使用示例

javaagent 技术是一个开发者可以构建一个独立于应用程序的代理程序(Agent),用来监测和协助运行在 JVM 上的程序,甚至能够替换和修改某些类的定义。有了这样的功能,开发者就可以实现更为灵活的运行时虚拟机监控和 Java 类操作了,这样的特性实际上提供了一种虚拟机级别支持的 AOP 实现方式,使得开发者无需对 JDK 做任何升级和改动,就可以实现某些 AOP 的功能了。
javaagent 选项支持在所有的JVM中使用Byteman。

1、示例1:加载规则文件并启动程序

1)、示例类

package com.win.byteman;
 
class App1
{
     public static void main(String[] args)
     {
         for (int i = 0; i < args.length; i++) {
             System.out.println(args[i]);
         }
     }
}

编译命令:javac -g com/win/byteman/App1.java

2)、规则

app1.btm

RULE trace main entry
CLASS App1
METHOD main
AT ENTRY
IF true
DO traceln("entry main")
ENDRULE
 
RULE trace main exit
CLASS App1
METHOD main
AT EXIT
IF true
DO traceln("exit main")
ENDRULE

3)、提交规则

script用于指示 Byteman 规则文件的位置。
Byteman agent 读取到这个选项之后从规则文件中加载和注入Byteman规则。如果要加载多个script:file规则文件,使用逗号(,)分隔即可。
执行命令:

java -javaagent:%BYTEMAN_HOME%/lib/byteman.jar=script:app1.btm com.win.byteman.App1 foo bar baz

4)、验证

在这里插入图片描述

2、示例2:启动程序并动态加载规则文件

这种方式利用javaagent启动程序,然后加载规则文件。

1)、示例类

package com.win.byteman;
 
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
class App4
{
           public static void main(String[] args) {
              new App4().start();
       }
 
       private void start() {
              new Thread(() -> {
                     DataInputStream in = new DataInputStream(System.in);
                     BufferedReader buf = new BufferedReader(new InputStreamReader(in));
                     try {
                            String next = buf.readLine();
                            while (next != null && !next.contains("end")) {
                                   consume(next);
                                   next = buf.readLine();
                            }
                     } catch (IOException e) {
                            e.printStackTrace();
                     }
              }).start();
       }
 
       public void consume(String text) {
              // 这是个局部变量,将会在byteman中追踪她
              final String arg = text;
              Thread thread = new Thread(() -> System.out.println("program confirm " + arg));
              thread.start();
              try {
                     thread.join();
              } catch (InterruptedException e) {
                     e.printStackTrace();
              }
              return;
       }
}

编译命令:javac -g com/win/byteman/App4.java

2)、规则

app4.btm

RULE trace main entry
CLASS App4
METHOD main
AT ENTRY
IF true
DO traceln("entry main")
ENDRULE
 
RULE trace main exit
CLASS App4
METHOD main
AT EXIT
IF true
DO traceln("exit main")
ENDRULE

3)、启动程序

在cmd中执行命令:

java -javaagent:%BYTEMAN_HOME%\lib\byteman.jar=listener:true,boot:%BYTEMAN_HOME%\lib\byteman.jar -Dorg.jboss.byteman.transform.all com.win.byteman.App4

Linux系统只需要把%BYTEMAN_HOME%换成${BYTEMAN_HOME}即可,注意Linux上分隔符是正斜杠,这个监听器会开启一个网络监听。
注意:当没有规则加载的时候,程序的行为不会发生任何变化,仅输出我们输入的内容。
如果执行成功,则出现如下界面
在这里插入图片描述

4)、提交规则

新打开一个cmd
执行命令:bmsubmit -l app4.btm
执行成功,如下界面
在这里插入图片描述

5)、验证

在另外一个cmd中输入要测试的字符串,成功则如下图
在这里插入图片描述

6)、卸载脚本

在执行bmsubmit的cmd中执行命令:bmsubmit -u app4.btm
卸载完成后的界面:
在这里插入图片描述
运行程序的界面测试结果如下:
在这里插入图片描述
在实际生产中,该种方法基本上不会使用到,因为要么是程序已经运行,要么是没有运行。已经运行的程序基本不会使用javaagent作为参数来运行,没有运行的程序一般使用第一种方式或其他的方式。常见的运行程序加载规则的是第三种方式,也即针对已经运行的程序进行监控。

3、示例3:动态安装agent到正在运行的程序中

1)、 示例类

package com.win.byteman;
 
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
class App4
{
           public static void main(String[] args) {
              new App4().start();
       }
 
       private void start() {
              new Thread(() -> {
                     DataInputStream in = new DataInputStream(System.in);
                     BufferedReader buf = new BufferedReader(new InputStreamReader(in));
                     try {
                            String next = buf.readLine();
                            while (next != null && !next.contains("end")) {
                                   consume(next);
                                   next = buf.readLine();
                            }
                     } catch (IOException e) {
                            e.printStackTrace();
                     }
              }).start();
       }
 
       public void consume(String text) {
              // 这是个局部变量,将会在byteman中追踪她
              final String arg = text;
              Thread thread = new Thread(() -> System.out.println("program confirm " + arg));
              thread.start();
              try {
                     thread.join();
              } catch (InterruptedException e) {
                     e.printStackTrace();
              }
              return;
       }
}

2)、规则

app4.btm

RULE trace main entry
CLASS App4
METHOD main
AT ENTRY
IF true
DO traceln("entry main")
ENDRULE
 
RULE trace main exit
CLASS App4
METHOD main
AT EXIT
IF true
DO traceln("exit main")
ENDRULE

3)、启动程序

在cmd中执行。
编译程序

Javac com/win/byteman/App4.java

启动程序

Java com.win.byteman.App4

测试程序
在这里插入图片描述

4)、建立监控

在新的cmd中找到进程号

1、执行jps

在这里插入图片描述

2、建立监控命令

在这里插入图片描述
如果成功,则在运行程序控制台输出:
Setting org.jboss.byteman.transform.all=

5)、提交规则

在cmd中执行命令:bmsubmit -l app4.btm
执行成功,则如下图
在这里插入图片描述
下载规则,执行命令:bmsubmit -u app4.btm

6)、验证

在程序运行控制台输入testing again,则出现如下界面
在这里插入图片描述
完整的操作两个cmd截图如下:
一个是程序运行控制台,一个是监控cmd
在这里插入图片描述

以上,简单的介绍了byteman脚本编写及示例、javaagent和byteman结合三种情况使用详细示例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一瓢一瓢的饮 alanchanchn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值