2010-03-21 13 views
5

W pewnych dobrze zrozumiałych okolicznościach nasza aplikacja otworzy zbyt wiele gniazd (połączeń z bazami danych) i osiągnie maksymalne otwarte pliki, na które pozwala system operacyjny. Rozumiemy to; naprawiamy problem, a także podnosimy limit.Dlaczego wirtualna maszyna wirtualna Java nie jest odtwarzana po błędach "Zbyt wiele otwartych plików"?

Nie możemy wyjaśnić, dlaczego niektóre części naszej aplikacji nie są odzyskiwane nawet po zaniku liczby połączeń, a my osiągnęliśmy limit.

W tym przypadku jest to aplikacja działająca pod Tomcat.

Kiedy to nastąpi, musimy najpierw zacząć widzieć „Zbyt wiele otwartych plików” błędów:

SEVERE: Socket accept failed 
java.net.SocketException: Too many open files 
     at java.net.PlainSocketImpl.socketAccept(Native Method) 
     at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:390) 
     at java.net.ServerSocket.implAccept(ServerSocket.java:453) 
     at java.net.ServerSocket.accept(ServerSocket.java:421) 
     at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:61) 
     at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:310) 
     at java.lang.Thread.run(Thread.java:619) 

końcu zaczniemy widząc NoClassDefFoundError s wewnątrz wątku aplikacji, która próbuje otworzyć połączenia http:

java.lang.NoClassDefFoundError: org/apache/commons/httpclient/protocol/ControllerThreadSocketFactory 
     at org.apache.commons.httpclient.protocol.DefaultProtocolSocketFactory.createSocket(DefaultProtocolSocketFactory.java:128) 
     at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707) 
     at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.open(MultiThreadedHttpConnectionManager.java:1349) 
     [...] 
Caused by: java.lang.ClassNotFoundException: org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory 
     at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1387) 
     at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1233) 
     at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) 
     ... 8 more 

Gdy błędne połączenia znikną, serwer ponownie zacznie akceptować połączenia, a wszystko wydaje się być w porządku, ale pozostaniemy z tym ostatnim błędem nieustannie wypluwanym na stderr.

Mimo że aplikacja zazwyczaj rejestruje nieobciążone klasy na standardowe wyjście, nie widzę takich dzienników tuż przed, podczas lub po błędach "Zbyt wiele otwartych plików".

Moja wstępna teoria głosiła, że ​​JVM Hotspot rozładowałby pozornie nieużywane klasy, gdy napotka "Zbyt wiele otwartych plików", ale jeśli tak, to nie rejestruje tego faktu.

Edit: Jako Stephen C wskazuje poniżej, jeśli jest rozładunku klasę i napotka błąd po raz pierwszy go przeładowuje, które mogłyby wyjaśnić, dlaczego nigdy nie odzyskuje. Myślę, że to dobra teoria pracy. Czy jest to udokumentowane w dokumentach Sun? Dlaczego nie logowałby się, że klasa jest rozładowywana w taki sposób, jak zwykle ma to miejsce w przypadku wyładowania klasy?

szczegóły Platforma:

Java(TM) SE Runtime Environment (build 1.6.0_14-b08) 
Java HotSpot(TM) 64-Bit Server VM (build 14.0-b16, mixed mode) 

Apache Tomcat Version 6.0.18 

Odpowiedz

1

Myślę, że powodem są coraz powtarzające ClassNotFoundExceptions jest to, że pierwsza próba klasy inicjalizacji ControllerThreadSocketFactory powiodło się z powodu problemu szczelności gniazda. Twój kod wykonuje teraz wiele czynności inicjujących inicjowanie klasy dla klasy i zgłasza pierwotny problem.

Jeśli inicjalizacja klasy zawodzi po raz pierwszy, to koniec. JVM nie będzie próbować robić tego ponownie.

+0

Zainicjowano ControllerThreadSocketFactory i nawiązujemy połączenia HTTP przez pewien czas przed pierwszym błędem. W typowym przypadku aplikacja działa przez ponad 12 godzin przed utratą połączenia z bazą danych, co powoduje wyczerpanie deskryptora pliku. Następnie otrzymujemy wyjątek ClassNotFound, połączenia HTTP nie mogą być ustanowione i nigdy się nie odzyskuje. Wygląda na to, że JVM rozładowuje klasę, a następnie nie może jej ponownie załadować. –

+0

@Michael ... a powodem, dla którego nie może go ponownie załadować, jest to, co podano w mojej odpowiedzi. –

+0

Więc myślisz, że JVM rozładowuje klasę, gdy napotka błąd? Czy to gdzieś dokumentuje? –

0

Wobec tego samego problemu za pomocą Weblogic 8.1/JRockIt R27.2 i kilka webapps, który próbuje załadować resourcebundles, a następnie kończy się niepowodzeniem ze względu na ograniczenie liczby otwartych plików. Zatrzymanie i uruchomienie aplikacji (np. Wyładowanie i załadowanie programów ładujących klasy) sprawiają, że wszystko działa ponownie.

Powiązane problemy