首页 > 编程语言 >2、【java程序运行监控byteman】使用示例(运行中方法耗时监控、javaagent监控、jvm监控、规则的检查、是否运行以及查看等)

2、【java程序运行监控byteman】使用示例(运行中方法耗时监控、javaagent监控、jvm监控、规则的检查、是否运行以及查看等)

时间:2023-06-16 17:38:18浏览次数:55  
标签:程序运行 java byteman thread 示例 start 监控 btm main

(文章目录)


本文介绍了byteman的其他几种应用场景及示例,比如javaagent、监控jvm、bmjava命令、如何查看运行的规则、检查规则的正确性、检查规则是否在运行中等。 本文分为2个部分,即运行中方法耗时监控和其他示例。

一、 统计方法耗时(程序运行中)

该类是实时显示控制台输入的结果以及输入的是end时退出。 程序运行中是表示程序处于运行中进行某些方法的耗时监控。

1、创建示例类

package com.win.byteman;
 
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
 
/**
 * @author alan 2018年12月26日
 */
public class WorkerDemo {
   public static void main(String[] args) {
      WorkerDemo workerDemo = new WorkerDemo();
      DataInputStream dataInputStream = new DataInputStream(System.in);
      BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(dataInputStream));
      try {
         String next;
         while ((next = bufferedReader.readLine()) != null) {
            System.out.println(
                   "==========================================开始调用==========================================");
            workerDemo.working(next);
            System.out.println(
                   "==========================================结束调用==========================================");
            if (next.contains("end")) {
                break;
            }
         }
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
 
   private void working(String input) {
      System.out.println("输入内容:" + input);
//    try {
//       TimeUnit.SECONDS.sleep(2);
//    } catch (InterruptedException e) {
//       e.printStackTrace();
//    }
   }
}

2、建立监控

1)、获取运行程序的进程号

在cmd中输入jps,结果如下图: 在这里插入图片描述

2)、建立监控

在cmd中执行命令

bminstall -b -Dorg.jboss.byteman.tranform.all 13456

在这里插入图片描述

3、编制脚本

WorkerDemo.btm 文件存储在:D:\application\byteman-download-4.0.5\sample\testing 规则如下:

RULE trace worker time start
 
CLASS WorkerDemo
METHOD working(String)
AT ENTRY
IF TRUE
DO createTimer($0)
ENDRULE
 
RULE trace worker time stop
CLASS WorkerDemo
METHOD working(String)
AT EXIT
IF TRUE
DO traceln("                           working method  spent [" + getElapsedTimeFromTimer($0) + "] ms                            ");
    deleteTimer($0);
ENDRULE

4、检测脚本

脚本检测需要建立起脚本与需要监控的类之间的关系。 目录需要切换到classes所在的目录,btm文件所在的目录以实际的为准,本示例中所在的地址是D:\application\byteman-download-4.0.5\sample\testing。 在cmd中将目录cd到classes所在的目录,然后执行命令

bmcheck -p com.win.byteman -cp . D:\application\byteman-download-4.0.5\sample\testing\WorkerDemo.btm

如果执行成功则如下图所示 在这里插入图片描述 否则则可能有异常抛出,例如 在这里插入图片描述 该异常的原因是在btm所在的目录找不到classes对应的包目录。 当然,如果方便起见,也可以将btm放在与classes目录下,统一切换到classes目录下操作即可。

5、提交脚本

同样,需要在classes目录下提交脚本,执行命令

bmsubmit -i D:\application\byteman-download-4.0.5\sample\testing\WorkerDemo.btm

如果成功则如下图所示 在这里插入图片描述

6、验证

在运行程序控制台输入任意参数,查看其结果 在这里插入图片描述

7、卸载脚本

卸载脚本就是不再对程序进行监控。在cmd中执行命令

bmsubmit -u D:\application\byteman-download-4.0.5\sample\testing\WorkerDemo.btm

在这里插入图片描述

二、其他示例

1、javaagent示例(程序未运行)

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]);
         }
     }
}

2)、编译及测试

通过cmd命令行进行编译。 cd到classes所在的目录(即包文件夹所在的目录)或者直接到类所在的目录进行编译,即 D:\application\byteman-download-4.0.5\sample\testing 或 D:\application\byteman-download-4.0.5\sample\testing\com\win\byteman 执行编译命令:

Javac com/win/byteman/App1.java
# 或
Java App1.java

完成上述步骤后,在cmd中运行编译后的classes文件,执行命令:

Java com.win.byteman.App1 testing

在这里插入图片描述 执行java命令时需要带上包名,同时需要切换目录至classes所在的目录

3)、编制脚本

该脚本放在与classes目录下,当然也可以放在其他地方,但是在执行脚本的时候需要加上脚本所在目录。 脚本中如果有中文,会出现乱码,具体不知道是规则脚本中不能有中文字符还是其他的原因。 脚本名称:app1.btm

RULE trace main entry

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

关于脚本说明: 该脚本有针对App1类的main方法两个规则。 第一个规则是进入该方法时输出:entering main 第二个规则是退出该方法时输出:exiting main

This script contains two rules both of which specify code to be injected into METHOD main of CLASS AppMain. The first rule is injected AT ENTRY i.e. at the start of the method. The code to be injected is the IF DO part. In the first rule it calls builtin operation traceln(String) which prints its argument to System.out() followed by a newline . The second rule is injected AT EXIT i.e. at the point(s) where control returns from method main. Both rules specify condition IF true which means the DO part is always executed. You can supply a different Java expression if you want to compute whether or not the actions following DO are run.

4)、运行脚本

运行脚本的命令根据实际需要而定。 运行命令时需要关注btm文件所在的位置,本示例是放在classes所在的目录,如果不在该目录下则直接带上绝对地址即可。 当然在运行脚本前也可以通过bmcheck命令检查脚本是否合法,具体参考本文的第一个示例中的检测脚本章节。 The -javaagent option used to run the progarm with these Byteman rules is supported by all the main desktop and server JVMs. The syntax is

-javaagent : path_to_agent_jar = agent_option1 , agent_option_2 , . . .

The Linux command to run the program with Byteman and this rule set is

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

or on Windows

java -javaagent:%BYTEMAN_HOME%\lib\byteman.jar=script:app1.btm com.win.byteman.App1 testing again

命令说明: 告诉虚拟机在哪里找到agent的jar,本机是%BYTEMAN_HOME%\lib\byteman.jar 本示例中仅是the = sign,指定规则script:app1.btm。agent通过加载的btm文件读取操作,如果需要加载更多的btm文件则配置更多的btm文件即可。 -javaagent是java命令的一个参数,com.win.byteman.App1 foo bar baz 是java执行的具体的类及传递的参数。

The value after the : tells the JVM where to find the Byteman agent jar, ${BYTEMAN_HOME}/lib/byteman.jar. We only supply one agent option following the = sign, script:app1.btm, specifying the location of the Byteman rule script. The Byteman agent reads this option then loads and injects the rules from file app1.btm. If we wanted to load more than one script we could provide multiple script:file agent options, separated by a comma.

When you pass -javaagent on the command line the Byteman agent starts executing during JVM startup before the application is run. So, it will read the rules and inject side effects into App1.main() before this method gets called. The output should be as follows.

5)、测试

运行脚本的结果正常的情况如下图: 在这里插入图片描述 异常的结果(之一)如下图: 在这里插入图片描述

2、监控jvm的类

1)、创建示例类

package com.win.byteman;
 
class App2
{
    public static void main(String[] args)
    {
        for (int i = 0; i < args.length; i++) {
            final String arg = args[i];
            Thread thread = new Thread(arg) {
                public void run() {
                System.out.println(arg);
                }
            };
 
            thread.start();
            try {
                thread.join();
            } catch (Exception e) {
            }
        }
    }
}

2)、编制脚本

该脚本放在与classes目录下,当然也可以放在其他地方,但是在执行脚本的时候需要加上脚本所在目录。 脚本名称:thread.btm

RULE trace thread start
CLASS java.lang.Thread
METHOD start()
IF true
DO traceln("*** start for thread: "+ $0.getName())
ENDRULE

规则说明: 该规则是监控Thread的start方法,输出跟踪的内容。

This rule is injected into METHOD start() of the JVM runtime CLASS java.lang.Thread. It prints a trace message pasted together using the String + operator. Now start() is an instance method so when it is called there is a specific Thread instance which is the target for the method call.

The special variable $0 can be used to refer to this target object. start() has no arguments but in other cases where there are the arguments to the call which triggers the rule they can be referenced using $1, $2 etc.

Byteman knows that $0 references a Thread object so it type checks the method invocation $0.getName() and verifies that the result type is String. The injected code makes a call this method, appends the result to the constant String and passes the result to method traceln() to be written to System.out.

3)、运行脚本

运行脚本,由于是监控jvm的类,所以需要按照如下的命令进行。 To run this program using the new script we modify the script: agent option to reference file thread.btm. But that's not enough if we want to inject code into JVM classes. We need to provide some extra options/arguments. On Linux:

java -javaagent:${BYTEMAN_HOME}/lib/byteman.jar=script:thread.btm,boot:${BYTEMAN_HOME}/lib/byteman.jar -Dorg.jboss.byteman.transform.all com.win.byteman.App2 foo bar baz

or on Windows:

java -javaagent:%BYTEMAN_HOME%\lib\byteman.jar=script:thread.btm,boot:%BYTEMAN_HOME%\lib\byteman.jar -Dorg.jboss.byteman.transform.all com.win.byteman.App2 foo bar baz

本示例是针对jvm的Thread进行监控,所以通过bootstarp classloader加载。

Class Thread is a JVM class which means it gets loaded by the bootstrap classloader. Byteman can only inject code into this class if the Byteman agent classes are also loaded by the bootstrap classloader. The extra agent option boot:${BYTEMAN_HOME}/lib/byteman.jar is appended after the script option (note the comma used as a separator). This makes sure that the byteman agent jar is installed into the bootstrap classpath.

Class Thread also happens to be in package java.lang. Normally Byteman is super-cautious and will not inject code into this package in case it beaks the JVM. If you really want to change methods of classes in this package you need to define the system property org.jboss.byteman.transform.all.

4)、验证

运行脚本的结果正常的情况如下图: 在这里插入图片描述

3、Bmjava命令的应用

例子参考监控jvm示例和本文中的统计方法耗时示例。 On Linux you can use the command script bmjava.sh to wrap up the -javaagent options for you. It looks very much like the java command but it accepts Byteman rule scripts on the command line and bundles them up as -javaagent script: options. It also automatically bundles in the byteman jar using the boot: agent option. So, using bmjava.sh the previous command line simplifies to

bmjava.sh -i thread.btm com.win.byteman.App2 foo bar baz

Notice that the flag used there is -i for load. On Windows if you are using byteman release 2.0.1 or later there is an equivalent script called bmjava.bat which you can execute using command bjava. So the previous command simplifies to

bmjava -i thread.btm com.win.byteman.App2 foo bar baz

Note that you need to add the installed bin directory ${BYTEMAN_HOME}/bin to your path in orderto be able to execute the script by name (on windows use %BYETMAN_HOME%/bin)

4、注入正在运行的类(jvm类)

本示例是监控运行中的Thread,监控普通的类是否可以使用本方式没有测试(理论上是可以的),同时,监控运行中的类也可以采用本文的统计方法耗时(程序运行中)部分的说明。

1)、创建示例类

package com.win.byteman;
 
import java.io.DataInputStream;
 
class App3
{
    public static void main(String[] args)
    {
        try {
        DataInputStream in = new DataInputStream(System.in);
        String next = in.readLine();
        while (next != null && next.length() > 0 && !next.contains("end")) {
        final String arg = next;
        Thread thread = new Thread(arg) {
            public void run() {
                System.out.println(arg);
            }
            };
        thread.start();
        try {
            thread.join();
        } catch (Exception e){
        }
        next = in.readLine();
        }
    } catch (Exception e) {
    }
    }
}

编译略。

2)、编制脚本

该文件在classes所在目录。 脚本名称:thread.btm

RULE trace thread start
CLASS java.lang.Thread
METHOD start()
IF true
DO traceln("----------------------- start for thread: "+ $0.getName())
ENDRULE

3)、建立监控

本示例中建立监控的方式,与本文中其他的方式有所不同,理论上应该都可以,但没有做测试。 The agent listener is enabled on the java command line using agent option listener:true. On Linux the command is this

java -javaagent:${BYTEMAN_HOME}/lib/byteman.jar=listener:true,boot:${BYTEMAN_HOME}/lib/byteman.jar -Dorg.jboss.byteman.transform.all com.win.byteman.App3

or on Windows

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

建立监控成功后测试,如下图: 在这里插入图片描述

4)、提交脚本

java -classpath %BYTEMAN_HOME%\lib\byteman-submit.jar org.jboss.byteman.agent.submit.Submit -l thread.btm

提交成功,则出现如下界面 在这里插入图片描述

5)、验证

在cmd中输入需要测试的内容,测试内容如下图红框中所示 在这里插入图片描述

5、如何查看在运行的规则

Running bmsubmit.sh again we can see that the rule has been successfully compiled. 执行命令:

bmsubmit.sh

输出:

# File thread.btm line 4
RULE trace thread start
CLASS java.lang.Thread
METHOD start()
AT ENTRY
IF true
DO traceln("*** start for thread: "+ $0.getName())
ENDRULE
Transformed in:
loader: sun.misc.Launcher$AppClassLoader@5acac268
trigger method: java.lang.Thread.start() void
compiled successfully

This time there is an extra line at the end of the output saying compiled successfully. This means the rule has been type-checked and executed. Type checking only happens when the rule is first triggered -- in this case when Thread.start() is called after typing in the line containing the word baz. If type checking had failed then execution of the injected code would be inhibited and the listing would include details of the type error. Injected code is only removed when the rule is unloaded.

6、如何在一个运行的程序中安装一个代理

参考本文的使用示例中统计方法耗时(运行中)的例子。

7、如何检查规则的正确性

使用bmcheck命令进行检查。

1)、示例规则-thread.btm

由于本示例使用的是Thread,jvm的类,所以不需要。

RULE trace thread start
CLASS java.lang.Thread
METHOD start()
IF true
DO traceln("----------------------- start for thread: "+ $0.getName())
ENDRULE
另外一种形式的规则设置
RULE trace thread start
CLASS Thread
METHOD start()
IF true
DO traceln("----------------------- start for thread: "+ $0.getName())
ENDRULE

On Linux you run command script bmcheck.sh

>bmcheck.sh thread.btm
#或者
>bmcheck.sh -p java.lang -cp . thread.btm

checking rule trace thread start parsed rule "trace thread start" for class java.lang.Thread type checked rule "trace thread start"

TestScript: no errors On Windows if you are usiing release 2.0.1 or later use the equivalent script bmcheck.bat.

> bmcheck thread.btm
# 或者
> bmcheck  -p java.lang -cp . thread.btm

checking rule trace thread start parsed rule "trace thread start" for class java.lang.Thread type checked rule "trace thread start"

TestScript: no errors

2)、示例规则-App1.btm

示例类:

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]);
         }
     }
}

编译完成后,做下面的操作。

This rule does not use the fully qualified name of the target class. That's ok because the agent notices when com.win.byteman.App1 gets loaded and realises that the rule applies to it. But when we are checking rules offline the application is not run so Byteman does not know which package to use to lookup the class mentioned in the rule. The -p flag can be used to suggest one or more package prefixes for the type checker to try.

RULE trace main entry
CLASS App1
METHOD main
AT ENTRY
IF true
DO traceln("进入 main")
ENDRULE
 
RULE trace main exit
CLASS App1
METHOD main
AT EXIT
IF true
DO traceln("退出 main")
ENDRULE
或者另外一种形式
RULE trace main entry
CLASS com.win.byteman.App1
METHOD main
AT ENTRY
IF true
DO traceln("进入 main")
ENDRULE
 
RULE trace main exit
CLASS com.win.byteman.App1
METHOD main
AT EXIT
IF true
DO traceln("退出 main")
ENDRULE

执行如下命令

bmcheck -p com.win.byteman -cp . app1.btm
#或者
bmcheck app1.btm

3)、验证

8、如何确定规则是否运行

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]);
         }
     }
}

2)、规则

app1.btm

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

Sometimes you may be unsure whether your rules are being injected correctly. Perhaps the target method is never executed. Perhaps the rule condition is always false. Or maybe a parse or type error is stopping them being executed. If you run Byteman in verbose mode you will see trace output telling you what Byteman is doing. Verbose mode is enabled by setting a system property 执行命令:

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

在这里插入图片描述 The trace is quite verbose but all the information you need is there if you look for it.

  • When class AppMain is loaded the trigger locations for each rule is identified and the rule code is injected

Next the main method gets called and you can see an execute message for the entry rule (you can ignore the messages about helper activation and rule installation just now or read the Ptrogrammer's Guide if you want them explained)

  • The execute message is followed by the the enter rule's trace message.
  • The main method prints all its its ouptut
  • Just before it returns there is another execute message for the exit rule (again, just ignore the messages about rule installation)
  • The second execute message is followed by the exit rule's trace message .

以上,本文介绍了byteman的其他几种应用场景及示例,比如javaagent、监控jvm、bmjava命令、如何查看运行的规则、检查规则的正确性、检查规则是否在运行中等。

标签:程序运行,java,byteman,thread,示例,start,监控,btm,main
From: https://blog.51cto.com/alanchan2win/6501275

相关文章

  • AI智能视频技术在安防监控领域的场景应用
    AI智能视频技术是一种基于人工智能、深度学习和计算机视觉等技术的视频处理技术。它可以通过对视频进行分析和识别,实现各种智能化应用,如视频监控、智能家居、自动驾驶等。目前,AI智能视频技术已经实现了人脸识别、行为分析、智能跟踪、场景分析、目标检测、图像增强等多种功能,可以......
  • 京东api接口获得jd商品分类源代码调用示例
    ​  京东商品分类接口的作用是提供一种获取商品分类信息的方式,可以帮助开发者在自己的应用程序中快速获取商品分类数据,从而实现更加精准的商品分类展示、搜索等功能。具体而言,京东商品分类接口(获取免费测试)的作用包括:1.精准地获取商品分类信息:通过商品分类接口,开发者可以获......
  • 京东api接口获得jd商品分类源代码调用示例
     京东商品分类接口的作用是提供一种获取商品分类信息的方式,可以帮助开发者在自己的应用程序中快速获取商品分类数据,从而实现更加精准的商品分类展示、搜索等功能。具体而言,京东商品分类接口(获取免费测试请私信)的作用包括:1.精准地获取商品分类信息:通过商品分类接口,开发者可以获取最......
  • Python使用HTTP隧道代码示例
    在本地代码中,嵌入隧道模式HTTP,HTTP模式:服务器端口账号密码,即可使用HTTP隧道代理来做访问#!-*-encoding:utf-8-*-importrequests#要访问的目标页面targetUrl="http://ip.hahado.cn/ip"#代理服务器proxyHost="ip.hahado.cn"proxyPort......
  • SNMP软件及性能监控
    SNMP(SimpleNetworkManagementProtocol)是一种用于网络管理的协议。通过SNMP,我们可以监测和管理网络设备、服务器等重要设备的性能和状况,从而确保网络的正常运行。但在开始使用之前,需要进行配置,以便使其正常工作。SNMP软件类型SNMP(SimpleNetworkManagementProtocol)软件可以帮助......
  • Unity 编辑器直接运行正常,打包后的程序运行异常问题
     打包后的程序运行报错:base="System.MissingMethodException:Defaultconstructornotfoundfortypelog4net.Repository.Hierarchy.Hierarchy\r\natSystem.RuntimeType.CreateInstanceMono(System.BooleannonPublic,System.BooleanwrapExceptions)[0x00076]in&l......
  • SpringMVC基础详解(包含示例)
    SpringMVC简介SpringMVC是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架,跟Spring,Mybatis框架并称为SSM。是由Spring官方提供的基于MVC设计理念的web框架也是基于Servlet封装的用于实现MVC控制的框架,实现前端和服务端的交互与Servlet技术功能相同,均是......
  • Qt编写视频监控系统79-四种界面导航栏的设计
    一、前言最初视频监控系统按照二级菜单的设计思路,顶部标题栏一级菜单,左侧对应二级菜单,最初采用图片在上面,文字在下面的按钮方式展示,随着功能的增加,二级菜单越来越多,如果都是这个图文上下排列的按钮,那左侧高度空间不够,比如在笔记本1366x768的分辨率上,左侧如果有七八个菜单按钮,那就......
  • iptables规则示例之只允许本地访问特定端口
    一、背景说明Iptables指的是用来管理Linux防火墙的命令程序,通常位于/sbin/iptables,属于“用户态”(UserSpace,又称用户空间)的防火墙管理体系;IPtables是工作在用户空间中,定义规则的工具,本身并不算是防火墙。我们可以理解为一个客户端工具,用户通过ipatbles这个客户端,将用户......
  • log4j.xml示例
    <?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPElog4j:configurationSYSTEM"log4j.dtd"><log4j:configurationxmlns:log4j="http://jakarta.apache.org/log4j/"debug="false"><ap......