Почему виртуальная машина Java не восстанавливается после ошибок «слишком много открытых файлов»? - PullRequest
5 голосов
/ 21 марта 2010

При определенных понятных обстоятельствах наше приложение откроет слишком много сокетов (соединений с базой данных) и достигнет максимально открытых файлов, которые позволяет ОС. Мы понимаем это; мы исправляем проблему, а также увеличиваем лимит.

То, что мы не можем объяснить, - это то, почему части нашего приложения не восстанавливаются даже после того, как число соединений уменьшится, и мы в пределах допустимого.

В данном случае это приложение, работающее под управлением Tomcat.

Когда это происходит, мы сначала видим ошибки «Слишком много открытых файлов»:

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)

В конце концов, мы начинаем видеть NoClassDefFoundError s внутри потока приложения, который пытается открыть 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

Когда пропадают ошибочные подключения, сервер снова начинает принимать подключения, и все кажется нормальным, но мы остаемся с последней ошибкой, постоянно выводимой в stderr.

Хотя приложение обычно регистрирует выгруженные классы на стандартный вывод, я не вижу таких журналов непосредственно перед, во время или после ошибок «Слишком много открытых файлов».

Моя первоначальная теория заключалась в том, что JVM Hotspot будет выгружать, казалось бы, неиспользуемые классы, когда обнаружит «Слишком много открытых файлов», но если это так, это не регистрирует факт.

Редактировать: Как Стивен С указывает ниже, если он выгружает класс и сталкивается с ошибкой при первой перезагрузке, это может объяснить, почему он никогда не восстанавливается. Я думаю, что это хорошая рабочая теория. Это документировано в документации Sun? Почему бы не регистрировать, что класс выгружается так, как обычно происходит выгрузка класса?

Детали платформы:

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

Ответы [ 2 ]

1 голос
/ 21 марта 2010

Я думаю, что причиной того, что вы получаете повторяющиеся ClassNotFoundExceptions, является то, что первая попытка инициализации класса ControllerThreadSocketFactory не удалась из-за проблемы утечки Socket. Ваш код теперь неоднократно делает вещи, которые запускают инициализацию класса для класса, и они сообщают об исходной проблеме.

Если инициализация класса в первый раз не удалась, то все. JVM не будет пытаться сделать это снова.

0 голосов
/ 14 апреля 2010

Столкновение с той же проблемой при использовании Weblogic 8.1 / JRockIt R27.2 и нескольких веб-приложений, которые пытаются загрузить пакеты ресурсов, а затем завершаются ошибкой из-за ограничения количества открытых файлов. Остановка и запуск приложения (то есть выгрузка и загрузка загрузчиков классов) заставляют все работать снова.

...