Блог пользователя ralekseenkov

Автор ralekseenkov, 14 лет назад, По-русски
Нечасто мне в последнее время приходится писать код. Думал в это воскресенье быстренько напишу за часок нужную мне вещь, но не тут то было. Все написал, все отлично, но иногда программа падала на разных ассертах и непонятно из-за чего. А вроде все детерминированно - в яве проблем с неициализированной памятью нет, никаких коллекций с негарантированным порядком обхода я не использовал... в основном использовались только циклы и массивы.

В итоге убил пол дня на дебаг нестабильной программы, и оказалось баг в JVM! Если в функцию передаешь Integer.MAX_VALUE и пытаешься его использовать справа в сравнении на меньше или равно, в цикле, иногда возвращается false.

Вот минимальный код на котором происходит проблема.
 1 public class Test {
2
3 public static void main(String[] args) {
4 for (int i = 0; ; i++) {
5 try {
6 go(Integer.MAX_VALUE);
7 } catch (Exception e) {
8 System.err.println("Failed after " + i + " iterations");
9 throw new IllegalStateException(e.getMessage());
10 }
11 }
12 }
13
14 private static void go(int maxSteps) {
15 int count = 1;
16 while (count <= maxSteps) {
17 if (count >= 10) {
18 break;
19 }
20 count++;
21 }
22
23 if (count != 10) {
24 throw new IllegalStateException("Count = " + count);
25 }
26
27 }
28
29 }

Выводит примерно следующее:
  Failed after 2402 iterations
Exception in thread "main" java.lang.IllegalStateException: Count = 2
at Test.main(Test.java:9)

Java:
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04-307-10M3261)
Java HotSpot(TM) 64-Bit Server VM (build 17.1-b03-307, mixed mode)

Был бы благодарен, если бы кто-нибудь потестил под разными системами - винда, линукс и отписался о результатах указывая OS и Java version.

UPD: спасибо всем откликнувшимся. видимо проблема в 64-битной JVM, проявляется на всех платформах. баг репорт отправлен в оракл, проходит скрининг http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7007863.
  • Проголосовать: нравится
  • +28
  • Проголосовать: не нравится

14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
На семерке не воспроизводится

java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) Client VM (build 17.1-b03, mixed mode, sharing)
14 лет назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится
Windows 7 x64
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) 64-Bit Server VM (build 17.1-b03, mixed mode)

Воспроизводится! На 6000-11000 итерации падает...
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    спасибо. возможно проблема наблюдается только в 64-bit JVM
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Да, скорее всего так и есть.
      Интересно посмотреть, что под линуксом.

      Кстати, под 32-bit с ключом -server тоже никаких глюков.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
WinXP SP2, 32 bit

java version "1.6.0_18"
Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
Java HotSpot(TM) Client VM (build 16.0-b13, mixed mode)

Все работает
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Да, под WinXP, 32bit и
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
Java HotSpot(TM) Client VM (build 10.0-b23, mixed mode, sharing)

нету бага.

Видимо, это проблема 64-битной Java-машины. У нее вообще достаточно много глюков - мы часто при разработке задач сталкиваемся с тем, что детерменированное решение работает совсем недетерменированное время - причем разбор от 1 до 3сек...
Под 32-битной системой при этом ничего такого нет.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Заметил еще интересную особенность - вылетает всего при count = 2, то есть получается, что один раз цикл нормально отрабатывает и тут же валится...
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Win7, 64bit, build "1.6.0_23-b05"
Failed after ~8000 iterations, Count=2.

Забавно :)
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
ubuntu 10.10, 64bit

Failed after 910 iterations
Exception in thread "main" java.lang.IllegalStateException: Count = 2
    at main.main(main.java:9)
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
java version "1.6.0_20"
OpenJDK Runtime Environment (IcedTea6 1.9.1) (Gentoo build 1.6.0_20-b20)
OpenJDK 64-Bit Server VM (build 19.0-b06, mixed mode)

Падает, опять же, с Count = 2.
Итераций в среднем 7500.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    IcedTea настолько совместим с Java 6, что даже баги те же? :)
    Хотя я точно не знаю насколько OpenJDK вообще отличается от JVM...
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      java version "1.6.0_23"
      Java(TM) SE Runtime Environment (build 1.6.0_23-b05)
      Java HotSpot(TM) 64-Bit Server VM (build 19.0-b09, mixed mode)

      Итераций стало в среднем на 1000 меньше, хотя может быть, это везение.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Gentoo, 64-bit

java version "1.6.0_23"
Java(TM) SE Runtime Environment (build 1.6.0_23-b05)
Java HotSpot(TM) 64-Bit Server VM (build 19.0-b09, mixed mode)

Failed after 5912 iterations

14 лет назад, # |
Rev. 2   Проголосовать: нравится +10 Проголосовать: не нравится
> Написал багрепорт на bugreport.sun.com. Посмотрим, что они ответят.

Прошу прощения за дубль. Внутренний ID бага 1939808, отпишусь, когда получу нормальный ID.
14 лет назад, # |
  Проголосовать: нравится +15 Проголосовать: не нравится
Написал багрепорт на bugreport.sun.com. Посмотрим, что они ответят.
  • 14 лет назад, # ^ |
      Проголосовать: нравится +12 Проголосовать: не нравится
    аналогично. я отправил репорт часов 6 назад - как только убедился что я не одинок, и эта проблема не специфична для mac os (т.к. оракл не поддерживает JVM под мак).
14 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
Win7, 64bit
java version "1.6.0_18"
Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
Java HotSpot(TM) 64-Bit Server VM (build 16.0-b13, mixed mode)

не воспроизводится :(
14 лет назад, # |
Rev. 2   Проголосовать: нравится +6 Проголосовать: не нравится
А вот запуск на сервере Codeforces:

Failed after 6777 iterations
Exception in thread "main" java.lang.IllegalStateException: Count = 2
        at Test.main(Test.java:9)

java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) 64-Bit Server VM (build 16.3-b01, mixed mode)

  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Отличный план.
    Может, стоит куда-нибудь эту тему повесить, чтобы кто-нибудь еще не напоролся во время контеста? Хотя тут такие условия воспроизведения жуткие.
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      могу сказать что условия воспроизведения не жуткие.

      я практически писал олимпиадную задачу. у меня была функция, которая должна была из клетки (X,Y) идти по квадратному полю в направлении (DX, DY), но делать не более чем K шагов. снаружи в функцию я передавал K, а когда мне нужно было дойти до границ поля то передавалась бесконечность в качестве K (Integer.MAX_VALUE) и функция выходила по другому условию.

      так что это пример из реальной жизни. в общей сложности потрачено 5 часов чтобы изолировать проблему.

      в качестве workaround можно использовать < вместо <=, или использовать число меньшее Integer.MAX_VALUE
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        ....или вести некоторые вычисления в лонгах. Аналогичный пример с Long.MAX_VALUE не падает с неверным сравнением.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    На codeforces используется 64-битная Java :(
    Мы на нее не переходим на своих инвокерах потому, что она крайне странно и недетерменированно ведет себя (сталкиваемся с этим постоянно на рабочих компах), да и вот багу тут такую нашли :)

    Кстати, если запускать в режиме интерпретации (без native code): java -Xint Test, то все нормально работает...
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Я думаю меня здесь не правильно поняли. 64-битная Java установлена на сервере с веб-приложением, а инвокеры работают на 32-битной платформе.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
This bug is not available.
More information is available at -http://developers.sun.com/resources/bugsFAQ.html#s4q2
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Ну так я и написал, что я получил только предварительный номер. Сам баг еще недоступен в базе. Я напишу, когда они мне вышлют письмо с нормальным номером.