2016-01-08 13 views
5

Mam klasyczny przykład Heisenbuga, który jest wyzwalany przez stan, którego wcześniej nie widziałem. Moja starsza aplikacja (około 100K sloc starego kodu) nie działa poprawnie w konkretnym przypadku, a samo włączenie JPDA do zdalnego debugowania zmienia to zachowanie wystarczająco, powodując, że aplikacja działa poprawnie: nie robiąc nic poza dodaniem "-Xdebug-Xnoagent -Xrunjdwp: transport = dt_socket, server = y, suspend = n, address = 6666 "do linii poleceń vm ukrywa błąd (z rzeczywistym połączeniem lub bez niego). Biorąc pod uwagę, że mam w pełni powtarzalny przypadek testowy, nie znoszę zbytnio go zakłócać zmianą kodu na wypadek, gdyby znowu się ukrył. I oczywiście dzieje się to tylko w produkcji.Prawdopodobne i nieprawdopodobne przyczyny Heisenbugs w Javie?

Zwykle od razu zakładam problem z gwintowaniem, ale a) zachowanie jest 100% niepowodzenie vs 100% pracy i b) nie ma jawnego wykorzystania wątków w ścieżce kodu, o której mowa. Nasz zespół próbował wymyślić listę innych przyczyn tego zachowania, więc pomyślałem, że być może umysł grupowy Stack Overflow może dodać trochę więcej.

heisenbug w Javie:

  • wątki: zła synchronizacja warunkach wyścigu, założenia dotyczące zamawiania.
  • Wyraźny kod debugowania/rejestrowania: zmiany w ścieżce kodu powodują/zapobiegają problemowi. Rzadziej zmiany poziomu logu mogą powodować zmiany w czasie (ponowne nawiązywanie wątków) i różnice w wykorzystaniu zasobów we/wy.
  • Biblioteki kodu rodzimego mogą przeciągać problemy w Heisenbugach innych niż java.
  • Oczekiwano, że finalizatory będą działać w sposób przewidywalny.
  • niewłaściwe założenia dotyczące słabych referencji.
  • Załóżmy, że pamięć podręczna o ustalonym rozmiarze nigdy się nie wypełnia.
  • spodziewając się unikatowości kodów hash.
  • założenie, że == działa na Ciągach (lub nie działa na Ciągach, które mogą być internowane w niektórych przypadkach).
  • Błąd VM (nah, to nigdy nie dzieje się;).
  • Błąd metod (y) testów. Zwłaszcza gdy istnieją ukryte zmienne, które zależą od sukcesu testu. (to wygląda na nasz rzeczywisty problem, sukces jednego testu doprowadził do wykonania przez klienta kolejnego testu, który nie powiódł się z powodu problemów z zasadami.) Awaria doprowadziła do uruchomienia trybu debugowania zgodnie z polityką, która zakończyła się sukcesem.) westchnienie)

Jakieś inne przypadki warte poznania?

Edits:

  • tak, JPDA umożliwić kod wykorzystuje składnię stary. Nie testowałem, czy użycie nowoczesnej składni zmienia zachowanie.
  • Ten specyficzny maszyna używa 1.8.0_45-B14 na JRE oraz HotSpot 64-bitowy serwer VM (build 25,45-B02)
  • natomiast kwestia ma być ogólnie kwestia podżeganie jest prawdziwe i aktualne. Ponieważ problem manifestuje się w wdrożonym systemie, jestem rozdarty pomiędzy chęcią zostawienia go działającego z opcją -Xdebug, aby działał, i chciał wyśledzić podstawowy błąd i go zabić.
  • źle działający program jest częścią wieloetapowego potoku przetwarzania danych - szczegóły nie powinny mieć znaczenia, ale najlepiej można je rozumieć jako samodzielną aplikację, która pobiera pewne informacje z bazy danych, a następnie używa jej do modyfikowania niektórych plików .Część systemu, która się łamie, wydaje się być taka, że ​​informacje z bazy danych nie są interpretowane poprawnie - wszystko z uszkodzonego obiektu ORM lub pamięci podręcznej. Kiedy jest "zepsuty", logika aplikacji, która określa, czy ma do wykonania zadanie (w oparciu o zawartość bazy danych), robi zły wybór dla wszystkich iteracji (tysiące iteracji, w tym wiele wywołań programu). Kiedy jest "działa" (jedyną różnicą jest to, że vm działa z opcją -Xdebug lub nie), aplikacja dokonuje poprawnych wyborów dla wszystkich iteracji. Jest całkowicie spójny w tej konfiguracji. Ten sam kod działający na różnych bazach danych nie kończy się niepowodzeniem. Istnieją pewne dowody (wcześniejsze niż moje zaangażowanie w ten kod), że podobne zachowanie było widoczne w przeszłości, które w tajemniczy sposób zaczęło działać po pozornie drobnych zmianach kodu ... zobacz "Heisenbug"
+0

W razie możliwości przebiję flagi. W szczególności debugowanie sprawia, że ​​podejrzewam JIT. – chrylis

+0

To pytanie może dostarczyć kilku interesujących informacji dla wielu z nas. Dlaczego ktoś chciałby go zamknąć? – Andres

+0

@ m.thome, czy mógłbyś wyjaśnić nieco dokładniej, co masz na myśli przez "zachowanie to 100% porażki a 100% pracy"? Rozumiem przez to, co to jest zachowanie, które nie działa w 100% lub w 100% przypadków? Co to jest Twoja aplikacja (np. Komputer, usługa sieciowa, autonomiczna aplikacja z pojedynczym wierszem, itp.)? Nie szukam poufnych informacji biznesowych, ale nieco więcej informacji pomogłoby mi w zawężeniu możliwych rozwiązań do palenia. – entpnerd

Odpowiedz

3

Miałem przypadek, w którym Awaria została wywołana przez funkcję oszczędzania energii na sprzęcie, która nigdy nie była aktywowana, gdy błąd był badany.

+0

To interesujące. Czym był sprzęt i jaka była funkcja oszczędzania energii? – entpnerd

+2

To było około 15 lat temu. Był to gruby klient punktu sprzedaży działającego na komputerze Compaq. Za każdym razem, gdy operator opuścił komputer, włączona została funkcja oszczędzania energii (dyski, monitor i procesor) i system się zawiesił. Nie naprawiliśmy tego, po prostu dezaktywowaliśmy oszczędność energii. – Andres

4

-Xdebug wydaje się być przełącznikiem zmiany zachowań. What are Java command line options to set to allow JVM to be remotely debugged? twierdzi, że dodanie go powoduje przejście z JIT do wszystkich interpretowanych. Inne wyrocznia java docs (for jrocket admittedly) wydają się wskazywać, że jest wolniejsza z jakiegoś nieokreślonego powodu i nie jest odpowiednia dla wdrożonych systemów.

Mogę sobie wyobrazić, że różne schematy GC mogą wprowadzać zmiany.

Powiązane problemy