0

我正在学习如何使用 btrace。为此,我创建了一个包含以下代码的 spring-boot 项目。

@Controller
public class MainController {
    private static Logger logger = LoggerFactory.getLogger(MainController.class);
    @ResponseBody
    @GetMapping("/testFile")
    public Map<String, Object> testFile() throws IOException {
        File file = new File("/tmp/a");
        if (file.exists()) {
            file.delete();
        }
        file.createNewFile();
        return ImmutableMap.of("success", true);
    }
}

然后我使用 启动项目mvn spring-boot:run,之后我写了一个 btrace 脚本,如下。

import com.sun.btrace.annotations.*;
import com.sun.btrace.BTraceUtils;

@BTrace
public class HelloWorld {

    @OnMethod(clazz = "java.io.File", method = "createNewFile")
    public static void onNewFileCreated(String fileName) {
        BTraceUtils.println("New file is being created");
        BTraceUtils.println(fileName);
    }
}

正如你所看到的,这个脚本在java.io.File#createNewFile被调用时应该打印一些东西,这正是上面的控制器所做的。然后我使用以下代码将 btrace 附加到正在运行的 spring-boot 项目。

btrace 30716 HelloWorld.java

30716是正在运行的spring-boot项目的PID。然后我尝试访问http://localhost:8080/testFile,我从正在运行的 spring-boot 项目中得到了以下额外的输出。

objc[30857]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/bin/java (0x10e2744c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x1145e24e0). One of the two will be used. Which one is undefined.
2019-01-04 11:24:49.003  INFO 30857 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-01-04 11:24:49.003  INFO 30857 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2019-01-04 11:24:49.019  INFO 30857 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 16 ms

我期待它输出New file is being created,但它没有。为什么?我做错什么了吗?

4

1 回答 1

0

您的跟踪方法onNewFileCreated(String fileName)不能用于拦截java.io.File.createNewFile(),因为签名不同意(createNewFile()不接受任何参数,而onNewFileCreated()有一个)。如果跟踪方法中有参数(除非它们有 BTrace 注释),BTrace 将尝试将它们“绑定”到被拦截方法中的参数。如果它不能这样做,它将无法成功拦截该方法。

尝试

@OnMethod(clazz = "java.io.File", method = "createNewFile")
public static void onNewFileCreated() {
    BTraceUtils.println("method createNewFile called");
}

或者

@OnMethod(clazz = "java.io.File", method = "createNewFile")
public static void onNewFileCreated(@ProbeMethodName String methodName) {
    BTraceUtils.println("method " + methodName + " called");
}

更新1:

首先,您使用的是什么版本的 JDK?BTrace 似乎不支持 JDK > 8 ( https://github.com/btraceio/btrace/issues/292 )。

其次,您可以尝试运行此跟踪脚本吗:

import com.sun.btrace.annotations.*;
import com.sun.btrace.BTraceUtils;

@BTrace
public class TracingScript {
    @OnMethod(clazz = "java.io.File", method = "createNewFile")
    public static void onNewFileCreated(@ProbeMethodName String methodName) {
        BTraceUtils.println("method " + methodName + " called");
    }
}

针对一个简单的测试应用程序:

import java.io.File;

public class FileCreator {

    public static void main(String[] args) throws Exception{
        for(int i = 0; i < 250; i++) {
            File file = new File("C://Temp//file" + i);
            if (file.exists()) {
                file.delete();
            }
            file.createNewFile();
            Thread.sleep(10000);
        }
    }
}

这适用于 BTrace 1.3.11.3(以及通过 BTrace Workbench JVisualVM 插件 0.6.8,这是我通常使用 BTrace 的地方)。

于 2019-01-04T05:41:37.797 回答