Mieliśmy osobliwy problem w naszym systemie produkcyjnym z powodu bardzo głupiego błędu w bibliotece klienta.

Co się stało, to:

public <T> ResponseEntity<T> executePut(String url, JsonObject payload, Class<T> t) {
       String payloadString = payload != null ? payload.toString() : null;
       HttpEntity<String> entity = new HttpEntity<>(payloadString, getCommonHeaders());
       restTemplate.getMessageConverters()
               .add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
       return restTemplate.exchange(url, HttpMethod.PUT, entity, t);
   }

Jak widać w powyższej metodzie, biblioteka klienta pobierała obiekt autowired (singleton) i kontynuowała dodawanie elementu na liście MessageConverters.

Problem: po chwili odwołanie do obiektu restTemplate dawało NPE również z pustym śladem stosu.

PS: Wskazuję na to jako prawdopodobną przyczynę, ponieważ jest to jedyna zmiana kodu, która nastąpiła między dwoma wdrożeniami.

Ponadto, czy duży obiekt nie powinien powodować braku pamięci? W naszym przypadku tak się nie stało i inne przepływy aplikacji działały bez zarzutu.

0
The-Proton-Resurgence 21 listopad 2019, 10:57
 – 
Ng Sharma
21 listopad 2019, 11:03
Myślę, że mój problem jest subtelnie inny niż pytanie w twoim linku, wyraźnie miał BRAK PAMIĘCI, ale nie mam takiego wyjątku.
 – 
The-Proton-Resurgence
21 listopad 2019, 11:06
Gdy zabraknie pamięci, ślad stosu może nie zostać wyświetlony (ponieważ nie ma na to wystarczającej ilości pamięci).
 – 
Kayaman
21 listopad 2019, 11:22
Więc co sprawia, że ​​myślisz, że twój problem jest związany z pamięcią sterty? Nie widzę na to żadnych wskazówek. Spróbuj użyć debugera i wyszukaj, gdzie został zgłoszony NPE. Dostosuj swoje pytanie, jeśli dowiesz się więcej.
 – 
Jochen Reinhardt
21 listopad 2019, 11:37
To właśnie mówię, nie mam powodu, by sądzić, że to problem ze stertą, ponieważ aplikacja wydawała się działać poprawnie. Moje pytanie próbuje zrozumieć, co mogło spowodować problem?
 – 
The-Proton-Resurgence
21 listopad 2019, 12:08

1 odpowiedź

Gdy obiekt stanie się zbyt duży, aby zużywał całą pamięć sterty, maszyna wirtualna przestanie działać poprawnie. Jest mało prawdopodobne, że jakakolwiek część programu uruchomiona w tej maszynie wirtualnej będzie nadal działać poprawnie.

Kiedy sterta się zapełnia, garbage collector próbuje zwolnić pamięć. I będzie próbował to robić cały czas. Twoja maszyna wirtualna nie zrobi nic więcej. I najprawdopodobniej otrzymasz OutOfMemoryError: GC Overhead Limit Exceeded. Zobacz https://www.baeldung.com/java-gc-overhead-limit -przekroczono

Ten błąd nie powinien być obsługiwany przez kod w programie. Jest mało prawdopodobne, że ktoś zwróci null w przypadku błędu braku pamięci. Uważam to za bardzo złe zachowanie.

Odnośnie wyjątku NullPointerException: nie sądzę, aby nie zawierał śladu stosu. Jednak może nie zostać zalogowany. Czy próbowałeś dołączyć debugger do systemu i ustawić punkt przerwania wyjątku dla NPE?

Wszystkie konwertery wiadomości w szablonie REST będą wywoływane jeden po drugim. Konwertery wiadomości dodajesz na początku listy przy każdym wywołaniu. Wydaje mi się, że to nie ma sensu. może powodować wewnętrzne problemy.

0
Jochen Reinhardt 21 listopad 2019, 11:18
1
Oczywiście powoduje to wewnętrzne kłopoty. On już to wie.
 – 
Kayaman
21 listopad 2019, 11:21
Nie jestem pewien, czy to jest odpowiedź na moje pytanie, w każdym razie bardzo dziękuję za wysiłek :)
 – 
The-Proton-Resurgence
21 listopad 2019, 12:13
Właściwie zapytałeś, co by się stało, gdyby obiekt java stał się zbyt duży. Myślę, że odpowiedziałem na pytanie. Jednak nadal będziesz musiał zbadać, dlaczego Twój program się nie powiedzie. Ale właściwie o to nie prosiłeś.
 – 
Jochen Reinhardt
21 listopad 2019, 12:15