【问题标题】:duplicate stack trace detection in javajava中的重复堆栈跟踪检测
【发布时间】:2016-05-16 03:14:27
【问题描述】:

我正在尝试找出一个好的散列函数或实用程序代码,可用于检查堆栈跟踪是否已经存在。

所以,到目前为止,我正在使用一个简单的逻辑来比较 前 2000 个字符和另外 2000 个字符(如果存在的话)。

这将完成这项工作,但是需要一个更具技术性的解决方案来完成它。

【问题讨论】:

  • 如何定义堆栈跟踪的副本?是(class.method.lineNumber)的重复数组
  • 是否会将堆栈跟踪转换为字符串,然后使用该字符串进行比较?
  • 因为这段代码必须在移动应用程序中运行,所以性能和内存都是一个问题。转换整个堆栈跟踪并与另一个作​​为字符串进行比较似乎非常昂贵的操作

标签: java hash duplicates stack-trace


【解决方案1】:

比如:

初始化:

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);
    }

【讨论】:

  • 这很好,但是对于在移动应用程序中运行代码来说,这看起来像是昂贵的操作。特别是当我将有一个堆栈跟踪注册表进行比较时
  • 当你已经有了堆栈跟踪的注册表,我认为这不过是它们的列表,你不能使用 Arrays.equals() 吗?可能是我错过了什么
【解决方案2】:

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

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

但是,值得注意的是,StackTraceElement.hashCode() 的实现引入了一些您可能希望考虑的问题。 StackTraceElement 的哈希码是通过对以下各项进行异或运算来计算的:

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

(如果文件名、声明的类或方法名未知,则对应的属性为null,计算时用0代替hash。)

如果动态生成的类是堆栈跟踪的一部分(常见于 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();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 2011-10-01
    • 2018-11-09
    • 2011-12-03
    • 1970-01-01
    • 1970-01-01
    • 2014-05-15
    相关资源
    最近更新 更多