在Java中重复堆栈跟踪检测

时间:2016-02-06 01:04:52

标签: java hash duplicates stack-trace

我试图找出一个好的哈希函数或实用程序代码,可以用来检查堆栈跟踪是否已经存在。

所以,我使用简单的逻辑进行比较 前两个字符和另外2000个字符,如果它存在则从部分引起。

这将完成这项工作,但是需要一种更加技术性的解决方案。

2 个答案:

答案 0 :(得分:0)

如下:

初​​始化:

StackTraceElement[] previous = null;
    StackTraceElement[] current = null;

假设此代码在main中的某处开始:

    StackTraceElement[] stackTrace = Thread.getCurrentThread().getStackTrace();
    if( previous == null )
    {
       previous = stackTrace;
    }
    else if( current == null )
    {
       current = stackTrace;
    }



    if ( Arrays.equals( current, previous ) )
    {
        duplicateStackTrace = true;
    }


    previous = current;
    current = null;

假设StackTraceElement的内置equals()函数适合您:

public boolean equals(Object obj) {
        if (obj==this)
            return true;
        if (!(obj instanceof StackTraceElement))
            return false;
        StackTraceElement e = (StackTraceElement)obj;
        return e.declaringClass.equals(declaringClass) &&
            e.lineNumber == lineNumber &&
            Objects.equals(methodName, e.methodName) &&
            Objects.equals(fileName, e.fileName);
    }

答案 1 :(得分:0)

我过去曾使用堆栈跟踪哈希来“抢占”异常,以便我可以更轻松地查看哪些错误最常见。实现堆栈跟踪哈希的最简单,最直接的方法是这样的:

public static int computeStackTraceHash(StackTraceElement[] trace) {
  return Arrays.hashCode(trace);
}

然而,值得注意的是StackTraceElement.hashCode()的实施引入了一些您可能希望考虑的皱纹。 StackTraceElement的哈希码是通过对以下内容进行异或来计算的:

  • fileName.hashCode()
  • lineNumber
  • declaringClass.hashCode()
  • methodName.hashCode()

(如果文件名,声明类或方法名称未知,则相应的属性将为null,并使用0而不是哈希进行计算。)

如果动态生成的类是堆栈跟踪的一部分(与Spring这样的库一样),跟踪中某些类的名称可能是随机的,这会破坏您的哈希值。因此,您可能希望在跟踪中检测这些类并省略它们。您可能还希望省略哈希计算中的行号,这将使您的“桶”更容忍代码中的微小更改。您的个人情况可能需要考虑其他事项。所以这可以改变你的计算看起来像这样:

public static int computeStackTraceHash(StackTraceElement[] trace) {
  List<Object> components = new ArrayList<>();

  for (StackTraceElement el : trace) {
    if (includeElement(el)) { // decide whether we're including this element
      components.add(el.getClassName());
      components.add(el.getMethodName());
    }
  }

  return components.hashCode();
}