我试图找出一个好的哈希函数或实用程序代码,可以用来检查堆栈跟踪是否已经存在。
所以,我使用简单的逻辑进行比较 前两个字符和另外2000个字符,如果它存在则从部分引起。
这将完成这项工作,但是需要一种更加技术性的解决方案。
答案 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();
}