为什么Java VM在“打开的文件太多”错误后无法恢复?

问题描述 投票:6回答:2

在某些容易理解的情况下,我们的应用程序将打开过多的套接字(数据库连接),并达到操作系统允许的最大打开文件数。我们了解这一点;我们正在解决此问题,同时也提高了限制。

我们无法解释的是,为什么即使连接数量减少后我们的应用程序的某些部分也无法恢复,而我们仍在限制之内。

在这种情况下,它是在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)

最终,我们开始在尝试打开HTTP连接的应用程序线程中看到NoClassDefFoundError

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。

尽管应用程序通常将卸载的类记录到stdout,但在“打开文件过多”错误之前,之中或之后,我看不到任何此类日志。

我的最初理论是,当Hotspot JVM遇到“打开的文件太多”时,它将卸载看似未使用的类,但如果是这样,它不会记录事实。

Edit:正如Stephen C在下面指出的那样,如果它正在卸载该类,并且在第一次重新加载该类时遇到错误,则可以解释为什么它永远无法恢复。我认为这是一个很好的工作理论。它在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
java tomcat jvm noclassdeffounderror
2个回答
2
投票

我认为您得到ClassNotFoundExceptions重复的原因是,由于套接字泄漏问题,ControllerThreadSocketFactory的首次尝试类初始化失败。您的代码现在正在反复执行为该类重新触发类初始化的操作,并且它们正在报告原始问题。

如果类初始化第一次失败,就是这样。 JVM不会再次尝试。


0
投票

使用Weblogic 8.1 / JRockIt R27.2和一堆试图加载资源束然后由于打开文件数限制而失败的webapp面对同样的问题。停止并启动应用程序(即,卸载和加载类加载器)会使事情再次起作用。

© www.soinside.com 2019 - 2024. All rights reserved.