2009-11-25 2 views
3

Мы, похоже, подвержены странной ошибке в нашей среде Java. У нас теперь было два случая одного и того же исключения «не может быть»; в одном случае проблема возникла 42,551 раз в течение 48 минут в процессе работы, а затем самопроизвольно очистилась.Работа над ошибкой JIT Java

Неисправный код запускается с помощью этой линии:

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

, где int source = 0 и long 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 он пишет хороший код.

У кого-нибудь есть опыт в том, чтобы обойти/диагностировать такую ​​проблему?

Roger.

+0

Жуткий ошибка. Грустные времена. –

+3

Какой JVM? Вы пытались «final» метод, который содержит эту строку, чтобы изменить обработку JIT? – omerkudat

+0

@omer - хорошее предложение. +1 –

ответ

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.

+0

Нет, мы не исключали никаких возможностей. Ошибка JIT - наша наиболее вероятная догадка, учитывая характер ошибки (и что программа - чистая Java). У нас может быть ошибка JVM-памяти, но факт, что он очищается спонтанно, кажется, подходит для jit-проблемы. –

+2

Фактически тот факт, что он спорадический и действительно, действительно странный, соответствует его аппаратной проблеме. Ошибки в JIT-компиляторе, среда JVM, хотя это возможно, маловероятны. –

0

Первое, что я хотел бы сделать, это проверить исходный код java.util.Formatter и посмотреть, выполняются ли какие-либо другие проверки, приводящие к исключению для символа шаблона 'd'. Какую версию Java вы используете?

+0

Мы проверили исходный код, мы используем jrockit R27.6.0-50_o-100423-1.6.0_05-20080626-2104-linux-x86_64. Исходный код 1.6 для Formatter.java выбрасывает, когда Conversion.isValid (c) завершается с ошибкой, это должно возвращать значение true, когда isInteger (char c) возвращает true, что должно быть как d, равно DECIMAL_INTEGER. Если это был неправильный формат кода, было бы странно, что код начинает работать, а затем останавливается, а затем перезапускается! –

+0

У вас есть источники для jrockit? Разве это не запатентованная JVM от Oracle? – jitter

+0

Нет, у нас есть источники солнца для классов java, и номера строк, похоже, соответствуют стеку вызовов, который мы получаем :-) –

0

Do:

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 и проследить через него, вручную, с этими значениями (звучит, как вы, возможно, сделали трассировку, но делать это может привести к фактическим значениям).

И, как говорили другие, случайные ошибки памяти также возможны здесь. Если возможно, запустите проверку памяти на аппарате и посмотрите (у меня были проблемы, убрав память заново).

+0

Увы, мы попытались запустить его с известными плохими значениями [доступными из полного журнала файл процесса], не справляясь с воспроизведением сбоя. Обратите внимание, что, учитывая местоположение стека вызовов, мы находимся в коде, создающем FormatSpecifier, когда возникает проблема, глядя на строку (фиксированный) формат «% 1d% XY% d» –

0

Вы уверены, что «d» в этом коде действительно ASCII d's, а не какой-то символ Юникода, который выглядит как d?

(Длинный выстрел, но странные вещи произошли.)

+0

«... и затем самопроизвольно очищается. " Да. –

1

Простой способ проверить, если это JIT ошибка это поставить вам код в цикле. Если это ошибка JIT, она не сработает внутри цикла, но не снаружи:

for (int i = 0; i < 100000; i++) { 
     String.format("%1d%XY%d", source, System.currentTimeMillis(), quoteID); 
    } 
+0

К сожалению, похоже, что это не так - если это ошибка jit, она выглядит одной из зависимых от выполнения. –

+0

Это слишком упрощенная модель того, как работает JIT в наши дни. JIT делает сложные решения относительно того, что компилировать, встроить и когда. –

1

Проверьте память! Например. с memtest86 +. Он доступен в меню загрузки cbb Ubuntu.

Смежные вопросы