私はJava Webホスティング会社によってホストされているアプリケーションを持っています。数日ごとに私のアプリは次のようにダウンします:
[2011-03-09 15:52:14,501] ERROR http-12021-9
Java.lang.OutOfMemoryError: unable to create new native thread
at Java.lang.Thread.start0(Native Method)
at Java.lang.Thread.start(Thread.Java:597)
ホスティング会社は、私のアプリがメモリをリークしていることを意味すると言いますが、私が持っているツールは空きメモリをまだ利用できます。エラーは常に新しいネイティブスレッドを作成しているので、問題はJVM config/OSリソースにあると思います。
このエラーの発生を防ぐにはどうすればよいですか?
Webサーバー側のJVMに問題がある可能性があります。詳細については、次のリンクを確認してください。
1つの可能性は、開いているファイルの数のユーザー制限に達していることです。
私は、すべてのプロセス/スレッドが1つ以上のファイル記述子を消費すると信じています。
たとえば、これがユーザーに対して発生した場合、シェルコマンドは実行するプロセスをフォークするため、「no」シェルコマンドが機能します(「-bash:fork:retry:リソースが一時的に利用できません」などのエラーが表示されます)。
私はこの問題にぶつかり、現在のユーザーだけがプロシージャを生成できなかったことがわかりました...他のユーザーは影響を受けませんでした。
解決するには、ulimit -n(開いている最大ファイル数)設定を上げます...詳細は次のとおりです。
次のコマンドでユーザー制限を確認できます。
ulimit -a
次の方法で最大ファイル制限を引き上げます。
ulimit -n 65536
これが私が今持っているものです:
$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 256797
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 75000
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 100000
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
システムのすべての明示的な制限を確認するには:
cat /etc/security/limits.conf
注意:私はOracle Linux6.3を使用しています-結果はディストリビューション間でわずかに異なる場合があります。
プロセスを起動すると、JVMのヒープサイズは制限されます(デフォルトは128MB)。そのサーバーにはもっと多くのメモリがあるかもしれませんが、JVMにはありません-あなたはそれをすべて使用しました。
これは-Xms
および-Xmx
コマンドライン引数で変更できますが、最初にメモリリークを見つけることをお勧めします:)
メモリートラッキングをしましたか? jconsoleを起動し、24時間にわたってメモリ消費量を監視またはログに記録します。 (平均して)ダウンせずにアップした場合は、メモリが不足しており、新しいスレッドの詳細を保存するのに十分なメモリがない可能性があります。
開いているファイルの数を処理するのはLinuxの問題です。次のように指定します。ulimit-n65536(uが指定できる任意の数)
この回答は、systemd経由でJavaを実行しているすべての人に向けられています。(例:自己作成のTomcatサービス)
JavaアプリケーションをTomcat経由でサーバー上で実行していました。また、便宜上systemdでサービスユニットを作成したので、サーバーの起動時に起動し、systemd(またはservice Tomcat restart
)経由で制御することもできます。 )。
ただし、systemdユニットとその最大許容タスク(スレッド)にはいくつかのデフォルト値があります。私のマシンでは、195タスクでした。サービスユニットの値をTasksMax=1024
で変更し、systemctl daemon-reload
でリロードすると、すべてが期待どおりに機能しました。
たとえば、/etc/systemd/system/Tomcat.service
のサービスユニットファイル
[Unit]
Description=Tomcat9
After=network.target
[Service]
Type=forking
User=Tomcat9
Group=Tomcat9
TasksMax=1048
Environment=CATALINA_PID=/opt/Tomcat/tomcat9.pid
Environment=Java_HOME=/usr/lib/jvm/default-Java
Environment=CATALINA_HOME=/opt/Tomcat
Environment=CATALINA_BASE=/opt/Tomcat
Environment="CATALINA_OPTS=-Xms2048m -Xmx28384m"
Environment="Java_OPTS=-Dfile.encoding=UTF-8 -Dnet.sf.ehcache.skipUpdateCheck=true -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC"
ExecStart=/opt/Tomcat/bin/startup.sh
ExecStop=/opt/Tomcat/bin/shutdown.sh
[Install]
WantedBy=multi-user.target
糸漏れのようです。スレッドは作成されますが、どこかにスタックします。スレッドを定期的にダンプして、割り当てられたスレッドの数が増えているかどうかを確認します。ダンプ内でスリープ/ハングしているスレッドを探します。
kill -QUIT jvm_pid