Java 获取String.equals调用跟踪

Java 获取String.equals调用跟踪,java,profiling,stack-trace,backtrace,log,Java,Profiling,Stack Trace,Backtrace,Log,我看到我可以像这样打印当前堆栈跟踪: 但是我想得到每个String.equals调用的跟踪,我不知道怎么做(因为我使用库,所以我不知道这些调用在哪里进行) 我想知道何时进行这些调用以提高代码的性能 编辑:根据答案的数量,可能我的问题不清楚: 我想在我的Java程序中跟踪String.equals()的每个调用,我不关心方法 java.lang.Runtime.traceMethodCalls(boolean on)方法启用/禁用方法调用的跟踪 以下示例显示lang.Runtime.traceM

我看到我可以像这样打印当前堆栈跟踪:

但是我想得到每个
String.equals
调用的跟踪,我不知道怎么做(因为我使用库,所以我不知道这些调用在哪里进行)

我想知道何时进行这些调用以提高代码的性能

编辑:根据答案的数量,可能我的问题不清楚:
我想在我的Java程序中跟踪
String.equals()
的每个调用,我不关心方法

java.lang.Runtime.traceMethodCalls(boolean on)方法启用/禁用方法调用的跟踪

以下示例显示lang.Runtime.traceMethodCalls()方法的用法

编译并运行上述程序,这将产生以下结果−

程序正在启动

正在启用跟踪

完成了

这是用于跟踪所有方法的,我将针对特定方法进行更新

您还可以尝试这样做:jcabi方面–记录Java方法执行

使用@Loggable annotation注释您的方法,每次调用它们时,您的SLF4J日志记录工具将收到一条消息,其中包含执行的详细信息和总执行时间:

            public class Resource {
              @Loggable(Loggable.DEBUG)
              public String load(URL url) {
                return url.openConnection().getContent();
              }
            }
类似的内容将出现在日志中:

[调试]#加载(“”):返回”

我非常怀疑许多JVM是否支持这一点。拦截每个方法调用的可能方法之一是使用指令插入字节码

问题是,类主要可以在加载类时插入指令。因此,虽然我建议的方法对应用程序类很有效,但JVM已经预加载了
String
类。要修改加载的类,JVM应该支持类
重传
或类
重定义
。您可以选择下一个简单的Maven项目:

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.stackoverflow.questions</groupId>
    <artifactId>stringequalscall</artifactId>
    <version>0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.0.2</version>
                <configuration>
                    <archive>
                        <manifestEntries>
                            <PreMain-Class>com.stackoverflow.questions.stringequalscall.Agent</PreMain-Class>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
src/main/java/com/stackoverflow/questions/stringequalscall/agentset.java:

package com.stackoverflow.questions.stringequalscall;

public class AgentTest {

    public static void main(String[] args) {
        System.out.println("Executing Agent test");
    }
}
构建JAR:

mvn clean install
并从您的
目标
文件夹运行

java -javaagent:stringequalscall-0.1-SNAPSHOT.jar com.stackoverflow.questions.stringequalscall.AgentTest
如果JVM支持上述加载的类操纵方法之一,那么您可以尝试编写自己的Java代理,将执行跟踪添加到
String#equals(String)

对于我来说,Oracle Java 9的输出是:

Can redefine classes: false
Can retransform classes: false
String modifiable: true
Executing Agent test
顺便问一下,为什么您认为
String#equals(String)
可能是性能问题的根源


另外,至少编写简单的Java代理很有趣。

我建议使用探查器。大多数探查器提供一个“热点”视图,您可以在其中看到
字符串.equals
方法,并可以打开其回溯,以查看方法调用的来源

与单独测量相比的另一个优势是,您可以评估它相对于其他热点的相对重要性

例如,在中,热点回溯如下所示:

如果
String.equals
不是热点,则可以将底部的视图过滤器设置为
java.lang.String
,以查看String类的所有录制方法


免责声明:我的公司开发了JProfiler

您正在做一个假设。您假设String.equals是一个主要的时间窃取者

绩效分析的关键是不要事先做出任何假设, 因为这样你就看不见程序告诉你什么需要时间,这可能是你所想的,但可能是别的


如何让程序告诉你什么需要时间。

Mmmm我真的不明白你的答案,我怎么能用它来跟踪每个String.equals调用,当我不知道它们在哪里时?我使用了Android Studio中包含的分析器,显然String.equals占用了整个时间的18.3%!(而String.chatAt可能被String.equals调用,占用了整个时间的13.3%)(我使用了独占时间)。此外,我仍在尝试为我的问题实施您的解决方案,谢谢;)从您的评论中可以看出,调整评测级别和/或期望使用的方法可能是正确的选择。代理在这里是一种过火的行为。我更新了我的Android Studio,现在我正在使用新的评测器,它非常适合我的问题,谢谢Aleh!
java -javaagent:stringequalscall-0.1-SNAPSHOT.jar com.stackoverflow.questions.stringequalscall.AgentTest
Can redefine classes: false
Can retransform classes: false
String modifiable: true
Executing Agent test