I w zasadzie tylko odpowiedział na to samo pytanie i trudne będę dzielić moją odpowiedź tutaj. Zachęcam do przeczytania complete answer available here. Spróbuję tu przedstawić podsumowanie i dostosować moją odpowiedź do obecnego kontekstu.
W pierwszej wersji Log4j udostępnia interfejs API do ręcznego wywoływania procedury zamykania. Z przyczyn, o których nie wiemy, it was removed from the second version. Teraz właściwym sposobem (zgodnie z nieistniejącą dokumentacją) jest zapewnienie własnej implementacji interfejsu ShutdownCallbackRegistry
, który jest odpowiedzialny za procedurę zamykania.
Proponowane rozwiązanie
Co zrobiłem, aby rozwiązać ten problem jest to, że realizowane własną wersję interfejsu ShutdownCallbackRegistry
. Zwykle robi to samo, co robi domyślna implementacja, ale zamiast rejestrować się jako przechwyt awaryjny na maszynie JVM, czeka na jej ręczne wywołanie.
Kompletne rozwiązanie i instrukcje można znaleźć na stronie GitHub/DjDCH/Log4j-StaticShutdown i można z niego korzystać we własnych projektach. Zasadniczo, na koniec, trzeba tylko zrobić coś takiego w swojej aplikacji:
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
try {
// Do your usual shutdown stuff here that need logging
} finally {
// Shutdown Log4j 2 manually
StaticShutdownCallbackRegistry.invoke();
}
}
}));
Nie mogę powiedzieć bez żadnej wątpliwości, że jest to idealne rozwiązanie i że moje wykonanie jest doskonałe, ale starałem zrobić to we właściwy sposób. Chętnie wysłucham opinii użytkowników, jeśli uznasz to rozwiązanie za odpowiednie lub nie.
Rejestrowanie, lub w zależności od innych usług w hakach wyłączania, od samego początku było kiepską praktyką, a teraz nadrabia zaległości. –
@MarkoTopolnik Jeśli uważasz, że jest to zła praktyka, co sugerujesz, czy wyjście wątku haka zamykającego wymaga nagrania/rejestracji? – vegemite4me
Ponieważ w haku zamknięcia nie można liczyć na jakąkolwiek część stanu inicjalizowanego, aby nadal istnieć, jedyną rzeczą, którą widzę jako pół-niezawodną, jest całkowicie samowystarczalny fragment kodu, który tworzy plik i zapisuje do niego. Podobnie do sposobu, w jaki tworzony jest zrzut rdzenia. –