Java StringBuilder.setLength(0)如何调用Arrays.fill?

Java StringBuilder.setLength(0)如何调用Arrays.fill?,java,arrays,jvm,stringbuilder,Java,Arrays,Jvm,Stringbuilder,在调查性能测试结果时,我发现Java Flight Recorder的“热方法”中报告了以下堆栈跟踪: 从堆栈跟踪来看,设置StringBuilder的长度会导致调用数组.fill。但是,我不明白为什么会发生这种情况,因为StringBuilder的长度设置为零 查看Log4j的RingBufferLogEvent.getMessageTextForWriting方法的代码,很明显StringBuilder的长度从未设置为零以外的任何其他值: // RingBufferLogEvent.java

在调查性能测试结果时,我发现Java Flight Recorder的“热方法”中报告了以下堆栈跟踪:

从堆栈跟踪来看,设置StringBuilder的长度会导致调用
数组.fill
。但是,我不明白为什么会发生这种情况,因为StringBuilder的长度设置为

查看Log4j的
RingBufferLogEvent.getMessageTextForWriting
方法的代码,很明显StringBuilder的长度从未设置为零以外的任何其他值:

// RingBufferLogEvent.java

private StringBuilder getMessageTextForWriting() {
    if (messageText == null) {
        messageText = new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE); // 128
    }
    messageText.setLength(0); // <-- this call. Note: new length is ALWAYS zero.
    return messageText;
}
newLength
始终为零时,
count
怎么可能是
true


JVM版本

Java HotSpot(TM)64位服务器虚拟机(25.144-b01),用于linux-amd64 JRE(1.8.0_144-b01),由“Java_re”于2017年7月21日21:57:33通过gcc 4.3.0 20080428(Red Hat 4.3.0-8)构建


(和Log4j 2.10.0)

JFR有一个问题。它以异步方式收集堆栈跟踪,也就是说,不只是在像这样的安全点。一方面,由于没有安全点偏差,这使得采样更加现实。另一方面,HotSpot JVM无法在任何随机时刻正确地遍历堆栈

HotSpot private API
AsyncGetCallTrace
尝试尽最大努力从计时器信号中断应用程序的任意点恢复当前堆栈跟踪。但是,代码中的某些位置对于堆栈遍历来说并不安全。如果在其中一个位置调用了
AsyncGetCallTrace
,它可能返回无效的堆栈跟踪或根本没有堆栈跟踪


这是已知的
AsyncGetCallTrace
问题。有实例和问题的分析。通常情况下,
AsyncGetCallTrace
(以及基于它的所有探查器)返回不准确的跟踪,其中一些帧被错误地替换为相邻方法。

您使用的是什么JDK?根据这段代码,
Arrays#fill
确实不应该到达。@Mureinik我更新了问题以添加版本信息。从代码上看确实不可能,除非之前打过电话it@Mureinik我相信
初始消息大小不会被系统属性覆盖,即使它是负数,
新字符[容量]
也会在AbstractStringBuilder构造函数中失败。这可能是来自
JIT
的优化,因此我添加了jvm标记。有一些非常棒的用户跟随这个标签,这可能会给我们带来一些启示-我希望你不要介意,见第1.4.1节,这可能有助于解决这个问题。@Klara这是一个不同的问题。
// RingBufferLogEvent.java

private StringBuilder getMessageTextForWriting() {
    if (messageText == null) {
        messageText = new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE); // 128
    }
    messageText.setLength(0); // <-- this call. Note: new length is ALWAYS zero.
    return messageText;
}
// AbstractStringBuilder.java

public void setLength(int newLength) {
    if (newLength < 0)
        throw new StringIndexOutOfBoundsException(newLength);
    ensureCapacityInternal(newLength);

    if (count < newLength) { // <-- how can this condition be true if newLength is zero?
        Arrays.fill(value, count, newLength, '\0');
    }

    count = newLength;
}