我有一个很少得到不正确值的变量。由于系统非常复杂,我无法跟踪值经过的所有代码路径 - 涉及多个线程,它可以保存然后从数据库加载等等。我将尝试使用代码图生成器来查看是否可以通过查看调用 setter 的方式来发现问题,也许还有其他一些技术。也许用一个跟踪它所经历的地方和变化的类来包装值(value)?我不确定这个问题是否足够清楚,但我很感激遇到这种情况的人的意见。
[编辑] 这个问题不容易重现,我无法在调试器中发现它。我正在寻找一种静态分析或日志记录技术来帮助追踪问题。
[编辑 2] 为了让事情更清楚,我所说的值是一个时间戳,表示为 64 位长变量中从 Unix 纪元 (01/01/1970) 开始的毫秒数。在某个未知点,值的前 32 位被截断,生成完全不正确(且不可恢复)的时间戳。
[编辑 3] 好的,感谢您的一些建议和几个小时的代码倾注,我找到了罪魁祸首。通过将基于毫秒的时间戳除以 1000 并将其存储在 int
变量中,将基于毫秒的时间戳转换为基于秒的时间戳。在稍后的代码中,基于秒的时间戳(一个 int
)乘以 1000 并存储到一个新的 long
变量中。由于 1000 和基于秒的时间戳都是 int
值,乘法的结果在转换为 long 之前被截断了。感谢所有提供帮助的人。
最佳答案
如果您使用一个 setter 并且只使用一个 setter 来设置您的值,您可以添加这些行以跟踪线程和堆栈跟踪:
public void setTimestamp(long value) {
if(log.idDebugEnabled) {
log.debug("Setting the value to " + value + ". Old value is " + this.timestamp);
log.debug("Thread is " + Thread.currentThread().getName());
log.debug("Stacktrace is", new Throwable()); // we could also iterate on Thread.currentThread().getStackTrace()
}
// check for bad value
if(value & 0xffffffff00000000L == 0L) {
log.warn("Danger Will Robinson", new IlegalValueException());
}
this.timestamp = value;
}
此外,检查包含该字段的类,并确保对它的每个引用都是通过 setter 完成的(即使是在私有(private)/ protected 方法中)
编辑
也许 FindBugs可以在静态分析方面提供帮助,我稍后会尝试找到确切的规则。
关于java - 如何在 Java 中跟踪值的来源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1620786/