【问题标题】:Out Of Memory Tomcat (unable to create new native thread)内存不足 Tomcat(无法创建新的本机线程)
【发布时间】:2015-02-19 12:46:20
【问题描述】:

在给定错误 tomcat is exit(shutdow) 之后,我的 1 个 tomcat 不断出现内存不足错误,我的应用程序在该 tomcat 中部署。

我拿了日志文件,发现了这个

SEVERE: Error allocating socket processor
java.lang.OutOfMemoryError: unable to create new native thread
    at java.lang.Thread.start0(Native Method)
    at java.lang.Thread.start(Thread.java:597)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.start(JIoEndpoint.java:513)
    at org.apache.tomcat.util.net.JIoEndpoint.newWorkerThread(JIoEndpoint.java:744)
    at org.apache.tomcat.util.net.JIoEndpoint.createWorkerThread(JIoEndpoint.java:723)
    at org.apache.tomcat.util.net.JIoEndpoint.getWorkerThread(JIoEndpoint.java:757)
    at org.apache.tomcat.util.net.JIoEndpoint.processSocket(JIoEndpoint.java:789)
    at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:355)
    at java.lang.Thread.run(Thread.java:619)
18 Feb, 2015 5:43:30 PM org.apache.tomcat.util.net.JIoEndpoint createWorkerThread
INFO: Maximum number of threads (750) created for connector with address null and port 80

我在 server.xml 中使用这个连接器设置

<Connector port="80" protocol="HTTP/1.1" 
               connectionTimeout="10000" maxThreads="750" minSpareThreads="50" redirectPort="8443" />

谁能建议我该怎么做?

线程转储

"http-80-123" daemon prio=6 tid=0x5f5e7400 nid=0xcfc runnable [0x619be000..0x619bf9e8]
   java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:129)
    at com.microsoft.sqlserver.jdbc.DBComms.receive(Unknown Source)
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(Unknown Source)
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PreparedStatementExecutionRequest.executeStatement(Unknown Source)
    at com.microsoft.sqlserver.jdbc.CancelableRequest.execute(Unknown Source)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeRequest(Unknown Source)
    - locked <0x15c69398> (a com.microsoft.sqlserver.jdbc.TDSWriter)

我在 20 秒内进行了 4 次线程转储,发现这个 tid 一直处于活动状态

我们能用这个转储找到什么吗?

我从线程转储中得到这个,这表明死锁条件'BLOCKED',因为我在相同状态下得到这个数次 80-90

"http-80-342" daemon prio=6 tid=0x5c0d7c00 nid=0x1d0c waiting for monitor entry [0x6ee0e000..0x6ee0fce8]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:247)
    at java.sql.DriverManager.getCallerClass(DriverManager.java:477)
    at java.sql.DriverManager.getConnection(DriverManager.java:576)
    at java.sql.DriverManager.getConnection(DriverManager.java:185)
    at t4u.common.DBConnection.getConnectionToDB(DBConnection.java:32)
    at t4u.functions.CommonFunctions.getProcessID(CommonFunctions.java:1465)

【问题讨论】:

    标签: java tomcat tomcat6


    【解决方案1】:

    java.lang.OutOfMemoryError: 无法创建新的本地线程

    这意味着您已经达到了 JVM 可以创建的线程数的限制。这可能是操作系统强加的限制,也可能是由于缺乏资源(如内存)。

    如果这是操作系统强加的限制,您可以提高它,前提是您对系统具有该级别的访问权限。

    如果它与内存有关,您需要增加可用内存(添加更多物理内存或增加 VM 上的内存)或降低每个线程的内存要求。稍后,您可以使用 JVM 的 -Xss 参数更改线程堆栈大小。要找到理想值,请从非常低的值开始,例如 128K 或 256K,然后查看是否有任何 StackOverflow 异常。如果你这样做,请增加直到它们消失。

    这里的另一种可能性是使用不同的连接器实现。您还没有说您当前使用的是哪一个,但是 BIO(阻塞 IO)连接器每个请求消耗一个线程。根据您的应用程序正在做什么,如果您使用 NIO 或 APR 连接器,您可能会看到更好的线程利用率(即处理相同数量的请求所需的线程更少)。这里没有足够的信息让我说出一种或另一种方式,但您可能想用您的应用对其进行测试,看看所需的线程数是否下降。

    信息:为地址为空且端口为 80 的连接器创建的最大线程数 (750)

    这看起来您可能在 Tomcat 中达到了线程池的限制。检查conf/server.xml 中的配置。如果您使用的是 Executor,请在该元素上查找 maxThreads。如果没有,请在 Connector 元素上查找 maxThreads

    【讨论】:

    • 感谢您的回复我已经编辑了问题,我还提到了 server.xml 中完成的连接器配置详细信息
    • 这很有帮助。您肯定会达到 maxThreads,您在连接器上将其设置为 750。它对 OOME 没有帮助,实际上它可能会使这种情况更有可能发生,但增加 maxThreads 将允许您超过池中的 750 个线程。同样,除非您有记忆力,否则这无济于事。请参阅我上面的处理建议。
    • 哦,你也在使用 BIO 连接器。 NIO 或 APR 可能有助于减少所需的线程数。多少,取决于你的工作量。大量的IO,你会看到更多的好处;大量的应用程序处理或 CPU 密集型任务,那么可能不会。不管怎样,如果你有一个测试环境,我建议你试一试看看会发生什么。
    • 所以您建议我使用 JVM 的 -Xss 参数更改线程堆栈大小。但是,在我的测试环境中,我没有收到这个错误,所以我被困住了如何进一步进行。在这种情况下,线程转储会有所帮助吗?
    • 我不能告诉你什么在这里可以工作,我对你的应用程序和你的环境了解不够。我上面的建议是您可以尝试的,可能有助于解决问题。最终,您需要进一步调查和测试以找到解决方案。你有一个开发环境,这很好。尝试对该环境施加一些负载,看看是否可以复制该问题。如果失败,请尝试通过增加堆栈大小或降低开发环境中的内存来使问题变得更糟,这可能会使复制变得更容易。那你可以试试上面的解决方案
    猜你喜欢
    • 2012-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-30
    • 2023-03-04
    • 2015-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多