3

在我们的 Java 环境中,我们似乎遇到了一个奇怪的错误。我们现在已经发生了两次相同的“不可能发生”异常;在一个案例中,问题在运行过程中的 48 分钟内发生了 42,551 次,然后自发地自行解决。

失败的代码由这一行触发:

return String.format("%1d%XY%d", source, System.currentTimeMillis(), quoteID);

在哪里int source = 0long quoteID = 44386874(例如)。

例外是:

java.util.UnknownFormatConversionException: Conversion = 'd'
        at java.util.Formatter$FormatSpecifier.conversion(Formatter.java:2605)
        at java.util.Formatter$FormatSpecifier.<init>(Formatter.java:2633)
        at java.util.Formatter.parse(Formatter.java:2479)
        at java.util.Formatter.format(Formatter.java:2413)
        at java.util.Formatter.format(Formatter.java:2366)
        at java.lang.String.format(String.java:2770)

检查代码'd'不应引发此异常。

我们想出的最好的解释是 JIT 编译器生成了错误的字节码,但在随后的重新 JIT 中它编写了好的代码。

任何人都有解决/诊断此类问题的方法的经验吗?

罗杰。

4

6 回答 6

7

我怀疑这是一个合法的 JIT 问题。

您是否排除了其他可能性,例如内存损坏或运行时环境问题?

您如何得出这是一个 JIT 问题的结论?

只是为了让您放心,这是引发异常的代码:

private char java.util.Formatter.FormatSpecifier.conversion(String s) {
    c = s.charAt(0);
    if (!dt) {
    if (!Conversion.isValid(c))
        throw new UnknownFormatConversionException(String.valueOf(c));

        ///////..........
}

和:

static boolean java.util.Formatter.Conversion.isValid(char c) {
    return (isGeneral(c) || isInteger(c) || isFloat(c) || isText(c)
        || c == 't' || c == 'c');
}

d是一个合法的整数标识符,isValid()应该返回True.

调试这不是问题,有根据的猜测会说你什么也找不到。这显然是内存损坏/环境问题。听起来这个问题很容易重现。尝试在不同的机器、不同的操作系统、不同的 JVM 上进行测试。

我的预感 - 你的问题不是 JIT 编译器。

于 2009-11-25T15:20:04.450 回答
1

测试内存!例如使用 memtest86+。它在 Ubuntu cd 启动菜单上可用。

于 2009-12-10T23:16:22.457 回答
1

检查它是否是 JIT 错误的一种简单方法是将代码置于循环中。如果它是 JIT 错误,它将在循环内部失败,但在外部不会:

for (int i = 0; i < 100000; i++) {
        String.format("%1d%XY%d", source, System.currentTimeMillis(), quoteID);
    }
于 2009-11-25T16:14:24.737 回答
0

我要做的第一件事是检查 java.util.Formatter 的源代码,看看是否有任何其他检查导致“d”模式字符出现异常。您使用的是哪个 Java 版本?

于 2009-11-25T15:27:49.433 回答
0

您确定该代码中的“d”确实是 ASCII d,而不是某些恰好看起来像广告的 Unicode 字符吗?

(长镜头,但奇怪的事情发生了。)

于 2009-11-25T15:51:38.760 回答
0

做:

final long time;

time = System.currentTimeMillis();

try
{
    return String.format("%1d%XY%d", source, time, quoteID);
}
catch(final UnknownFormatConversionExceptio ex)
{
    // log the source
    // log the time
    // log the quoteID
    throw ex;
}

如果那里看起来没有什么奇怪的,那么查看 String.format 的源并使用这些值手动跟踪它(听起来您可能已经完成了跟踪,但使用实际值进行跟踪可能会有所帮助)。

正如其他人所说,这里也可能出现随机内存错误。如果可能的话,在机器上运行内存检查并查看(我已经通过重新安装内存来解决问题......)。

于 2009-11-25T15:38:45.307 回答