技术标签: btrace
建议使用JDK8
Btrace可以动态地向目标应用程序的字节码注入追踪代码。
JavaComplierApi、JVMTI、Instrumentation+ASM
新建环境变量BTRACE_HOME
添加Path:%BTRACE_HOME%\bin
在JVisualVM中添加Btrace插件,添加classpath
使用命令行
btrace <pid> <trace_script>
pom文件添加Btrace依赖
<dependency>
<groupId>org.openjdk.btrace</groupId>
<artifactId>btrace-agent</artifactId>
<version>2.2.2</version>
<type>jar</type>
<scope>system</scope>
<systemPath>%BTRACE_HOME%\libs\btrace-agent.jar</systemPath>
</dependency>
<dependency>
<groupId>org.openjdk.btrace</groupId>
<artifactId>btrace-boot</artifactId>
<version>2.2.2</version>
<type>jar</type>
<scope>system</scope>
<systemPath>%BTRACE_HOME%\libs\btrace-boot.jar</systemPath>
</dependency>
<dependency>
<groupId>org.openjdk.btrace</groupId>
<artifactId>btrace-client</artifactId>
<version>2.2.2</version>
<type>jar</type>
<scope>system</scope>
<systemPath>%BTRACE_HOME%\libs\btrace-client.jar</systemPath>
</dependency>
编写一个测试方法
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController()
@RequestMapping("/btrace")
public class BTraceController {
@GetMapping("/arg1")
public String arg1(@RequestParam("name") String name){
return "Hello," +name;
}
}
Btrace追踪类
@BTrace
public class PrintArgsSimple {
@OnMethod(clazz = "com.whaleson.solar.practice.btrace.BTraceController",
method = "arg1",
location = @Location(Kind.ENTRY)//在什么时候拦截,entry是指入口的地方
)
public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args){
BTraceUtils.printArray(args);
BTraceUtils.println(pcn +"\t" + pmn);
}
}
启动服务并查看服务进程
jps -l
在Btrace追踪类的同级目录下执行
btrace 5680 PrintArgsSimple.java
@OnMethod(clazz="",method="")
@OnMethod(clazz="",method="<init>")
构造函数程序
@GetMapping("/construct")
public String construct(User user){
return user.toString();
}
public class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
拦截器
@BTrace
public class PrintConstructor {
@OnMethod(clazz = "com.whaleson.solar.domain.User",method = "<init>")
public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args){
BTraceUtils.printArray(args);
BTraceUtils.println(pcn +"\t" + pmn);
BTraceUtils.println();
}
}
同名函数程序
@GetMapping("/arg1")
public String same(@RequestParam("name") String name){
return "Hello," +name;
}
@GetMapping("/arg2")
public String same(@RequestParam("name") String name,@RequestParam("gender") String gender){
return "Hello," +name +"\t" +gender;
}
拦截器
@BTrace
public class PrintSame {
@OnMethod(clazz = "com.whaleson.solar.practice.btrace.BTraceController",
method = "same"
)
public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, String name,String gender){
BTraceUtils.println(pcn +"\t" + pmn);
BTraceUtils.println(name +"\t" + gender);
BTraceUtils.println();
Kind.ENNTRY
:入口,默认值Kind.RETURN
:返回编写方法类
@GetMapping("/construct")
public String construct(User user){
return user.toString();
}
拦截类
需要注意的是如果需要拦截返回值时,需要在拦截的请求参数上加
@Return
import org.openjdk.btrace.core.BTraceUtils;
import org.openjdk.btrace.core.annotations.*;
import org.openjdk.btrace.core.types.AnyType;
@BTrace
public class PrintReturn {
@OnMethod(clazz = "com.whaleson.solar.practice.btrace.BTraceController",
method = "construct",
location = @Location(Kind.RETURN)
)
public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, @Return AnyType arg){
BTraceUtils.println(pcn +"\t" + pmn);
BTraceUtils.println(arg);
BTraceUtils.println();
}
}
Kind.THROW
:异常异常类
@GetMapping("/exception")
public String exception(){
try {
System.out.println("start");
System.out.println(1/0);
System.out.println("end");
}catch (Exception e){
new Throwable("666");
}
return "succeed";
}
拦截类
import org.openjdk.btrace.core.BTraceUtils;
import org.openjdk.btrace.core.annotations.*;
/**
* This example demonstrates printing stack trace
* of an exception and thread local variables. This
* trace script prints exception stack trace whenever
* java.lang.Throwable's constructor returns. This way
* you can trace all exceptions that may be caught and
* "eaten" silently by the traced program. Note that the
* assumption is that the exceptions are thrown soon after
* creation [like in "throw new FooException();"] rather
* that be stored and thrown later.
*/
@BTrace
public class PrintOnThrow {
// store current exception in a thread local
// variable (@TLS annotation). Note that we can't
// store it in a global variable!
@TLS
static Throwable currentException;
// introduce probe into every constructor of java.lang.Throwable
// class and store "this" in the thread local variable.
@OnMethod(
clazz = "java.lang.Throwable",
method = "<init>"
)
public static void onthrow(@Self Throwable self) {
BTraceUtils.println(1);
currentException = self;
}
@OnMethod(
clazz = "java.lang.Throwable",
method = "<init>"
)
public static void onthrow1(@Self Throwable self, String s) {
BTraceUtils.println(2);
currentException = self;
}
@OnMethod(
clazz = "java.lang.Throwable",
method = "<init>"
)
public static void onthrow1(@Self Throwable self, String s, Throwable cause) {
BTraceUtils.println(3);
currentException = self;
}
@OnMethod(
clazz = "java.lang.Throwable",
method = "<init>"
)
public static void onthrow2(@Self Throwable self, Throwable cause) {
BTraceUtils.println(4);
currentException = self;
}
// when any constructor of java.lang.Throwable returns
// print the currentException's stack trace.
@OnMethod(
clazz = "java.lang.Throwable",
method = "<init>",
location = @Location(Kind.RETURN)
)
public static void onthrowreturn() {
BTraceUtils.println(5);
if (currentException != null) {
BTraceUtils.Threads.jstack(currentException);
BTraceUtils.println("=====================");
currentException = null;
}
}
}
Kind.Line
:行作用,查看指定行是否执行
测类方法
拦截类
@BTrace
public class PrintLine {
@OnMethod(clazz = "com.whaleson.solar.practice.btrace.BTraceController",method = "exception",
location = @Location(value = Kind.LINE,line = 31)
)
public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, int line){
BTraceUtils.println(pcn +"\t" + pmn);
BTraceUtils.println(line);
BTraceUtils.println();
}
}
拦截类
@BTrace
public class PrintArgComplex {
@OnMethod(clazz = "com.whaleson.solar.practice.btrace.BTraceController",
method = "construct",location = @Location(Kind.ENTRY))
public void print(@ProbeClassName String pcn, @ProbeMethodName String pmn, User user){
Field fieldName = BTraceUtils.field("com.whaleson.solar.domain.User", "name");
BTraceUtils.println(BTraceUtils.get(fieldName,user));
BTraceUtils.println();
}
}
执行拦截类
btrace 9684 PrintArgComplex.java
执行结果
btrace INFO: Attaching BTrace to PID: 9684
PrintArgComplex.java:3: 错误: 程序包com.whaleson.solar.domain不存在
import com.whaleson.solar.domain.User;
^
PrintArgComplex.java:14: 错误: 找不到符号
public void print(@ProbeClassName String pcn, @ProbeMethodName String pmn, User user){
^
符号: 类 User
位置: 类 com.whaleson.solar.utils.PrintArgComplex
BTrace compilation failed
执行时将User
类增加到classpath
btrace -cp "D:\workspace\idea\Solar\target\classes" 9684 PrintArgComplex.java
使用正则表达式匹配方法
import org.openjdk.btrace.core.annotations.BTrace;
import org.openjdk.btrace.core.annotations.Injected;
import org.openjdk.btrace.core.annotations.OnMethod;
import org.openjdk.btrace.core.annotations.ProbeClassName;
import org.openjdk.btrace.core.annotations.ProbeMethodName;
import org.openjdk.btrace.core.annotations.Self;
import org.openjdk.btrace.core.annotations.ServiceType;
import org.openjdk.btrace.services.impl.Printer;
/**
* This script traces method entry into every method of
* every class in javax.swing package! Think before using
* this script -- this will slow down your app significantly!!
*/
@BTrace
public class AllMethods {
@Injected(ServiceType.RUNTIME)
private static Printer printer;
@OnMethod(
clazz = "/javax\\.swing\\..*/",
method = "${m}"
)
public static void m(@Self Object o, @ProbeClassName String probeClass, @ProbeMethodName String probeMethod) {
printer.println("this = " + o);
printer.print("entered " + probeClass);
printer.println("." + probeMethod);
}
}
输出系统参数
import org.openjdk.btrace.core.BTraceUtils;
import org.openjdk.btrace.core.annotations.BTrace;
@BTrace
public class PrintJInfo {
static {
BTraceUtils.println("System Properties:");
BTraceUtils.printProperties();
BTraceUtils.println("VM Flags");
BTraceUtils.printVmArguments();
BTraceUtils.println("OS Enviroment");
BTraceUtils.printEnv();
BTraceUtils.exit(0);
}
}
默认只能本机调试;
生产环境下可以使用,
但是被修改的字节码不会被还原
。
比BTrace更强大的监控工具-阿里巴巴的Arthas
在Ubuntu中有如下几个文件可以设置环境变量 /etc/profile:在登录时,操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行. /etc/environment:在登录时操作系统使用的第二个文件,系统在读取你自己的profile前,设置环境文件的环境变量 ~/.profile:在登录时用到的第三个文件是.p
想要在VirtualBox运行任何系统,都需要有相应的ISO镜像文件,所以首先我们要获取ISO镜像文件。下边先介绍如何获取镜像文件:Step 1:从Mac App Store下载最新的Catalina 系统如果无法下载Catalina 系统,则直接跳到Step 2 结尾处下载 Catalina ISO文件Step 2:创建macOS Catalina ISO 文件找到你下载的macOS C...
Top31:RHEL-Linux上部署MariaDBMariaDB的由来:安装初始化操作允许远程访问,设置防火墙放行登录更改root密码创建账户查看账户信息对账户授权例:适用:RHEL8MariaDB的由来:由于MySQL的母公司Sun在2009 年被Oracle收购后,MySQL数据库项目也随之纳入Oracle麾下,逐步演变为保持着开源软件的身份,但又申请了多项商业专利的软件系统。开源软件是全球黑客、极客、程序员等技术高手在开源社区的大旗下的公共智慧结晶,自己的劳动成果被其他公司商业化自然也伤了一大
前言本文解决以下问题:SpringBoot中如何添加一个过滤器? 如何在过滤器中使用Bean? 如何判断请求的类型?GET还是POST? 如何获取请求中的参数? 如何重定向? 如何针对Ajax请求返回JSON串?如果你的关注点不在以上问题范围内,请路过。添加过滤器使用注解@WebFilter,并把它加到一个实现了Filter接口的类上,如下:@WebFilter(...
为大家简单介绍一下mybatis配置文件一些参数<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><co...
创建工程后目录结构:名称 作用 Listings 存放编译器编译时候产生的 c/汇编/链接的列表清单 Objects 存放编译产生的调试信息、 hex 文件、预览信息、封装库等 test目录存放 startup_MIMXRT1052.s、 MIMXRT1052.h、 main.c 文件MIMXRT1052xxxxx_flexspi_nor:复制存储器分配文...
参数T(v):变量v转为T类型基本数据类型转换 原类型 目标类型 方法 备注 整型、浮点型 整型、浮点型 T(v) 大数转小数超范围,溢出;浮点型转整型,小数丢失;高精度转低精度,精度丢失 任何类型 string fmt.Sprintf() 推荐 bool strconv.FormatBool(bool) int64 strconv.FormatInt(int64) ..
目前想到方法1,现有分词系统提出关键词,比如ansj,hannlp,word等2,基于tfidf 算权重3,基于textrank算法,部分分词系统采取textrank 算法4,基于语言模型,ngram 算下热度5,基于聚类打标签,比如基于lda6,基于语义和知识库知识对于内容分析 总结当前主要任务是段文本如何打标签准备,还需要很多实验要验证效果
新课上新,早鸟优惠价仅需99元! 每天前30人输入优惠码py30,立减30元! 60讲+源码+5门300元课程+讲师社群1V1答疑+社群闭门分享会=99元 10000+程序员联名推荐: 程序员必修的数据课,只看这个就够了! 【我们保证你能收获到这些:&nb...
原标题:小米10已停更半个月,基于安卓11的MIUI12即将到来目前MIUI12稳定版第一批已经推送,第二批预计7月初会陆续推送,而内测版这边,上边年两款旗舰小米10/Pro和RedmiK30Pro已经停更将近半个月,官方表示正在适配安卓11,也就是说,这两款机型内测版下次收到更新就会吃上安卓11! 值得注意的是,这次适配是适配基于安卓11的MIUI12,而非原生安卓11Beta包,根据以往经验,...
【oracle11g,18】存储结构:临时表,手工条带化,表/索引迁移表空间,删除表,外部表
回调函数(callbacks)(TensorBoard、EarlyStopping、ModelCheckPoint)本文主要介绍tf.Keras.callbacks中的三种回调函数:TensorBoard、EarlyStopping、ModelCheckPoint。TensorBoard:是Tensorflow自带的一个强大的可视化工具,也是一个web应用程序套件,它通过将tensor...