7

私はTomcat7を実行しています。サーバーは非常に強力で、8 GBRAM8コアです。

tomcatは、多くのメモリを無料で使用していますか?

私の問題は、サーバーがOnOutOfMemoryErrorを呼び出さなくても応答しなくなるまで、RESメモリがどんどん高くなっていることです。

Tomcat構成:

-Xms1024M
-Xmx2048M
-XX:PermSize=256m
-XX:MaxPermSize=512m
-XX:+UseConcMarkSweepGC
-XX:OnOutOfMemoryError='/var/tomcat/conf/restart_tomcat.sh'

メモリ情報:

Memory:     Non heap memory = 106 Mb (Perm Gen, Code Cache),
Loaded classes = 14,055,
Garbage collection time = 47,608 ms,
Process cpu time = 4,296,860 ms,
Committed virtual memory = 6,910 Mb,
Free physical memory = 4,906 Mb,
Total physical memory = 8,192 Mb,
Free swap space = 26,079 Mb,
Total swap space = 26,079 Mb
Perm Gen memory:    88 Mb / 512 Mb    ++++++++++++
Free disk space:    89,341 Mb 

Tomcatが使用するメモリは、topコマンドと比較してそれほど高くは見えません。

アプリのメモリグラフ

java.net.SocketException: No buffer space availableSMTPサーバーに接続しようとしたときやFacebookサーバーに接続しようとしたときにも発生しました。

私はHibernateを使用し、この構成ではc3p0接続プールを使用します。

        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://urldb/schema?autoReconnect=true</property>
        <property name="hibernate.connection.username">username</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <property name="hibernate.connection.password"></property>
        <property name="connection.characterEncoding">UTF-8</property>

        <property name="hibernate.c3p0.acquire_increment">1</property>
        <property name="hibernate.c3p0.idle_test_period">300</property>
        <property name="hibernate.c3p0.timeout">5000</property>
        <property name="hibernate.c3p0.max_size">50</property>
        <property name="hibernate.c3p0.min_size">1</property>
        <property name="hibernate.c3p0.max_statement">0</property>
        <property name="hibernate.c3p0.preferredTestQuery">select 1;</property>
        <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>

何も見つかりませんでした...誰かが私がどこを探すべきかについてのヒントを持っていますか?

ありがとう!

[更新1]ヒープダンプ:

HEAP HISTOGRAM :

class [C                                    269780  34210054
class [B                                    5600    33836661
class java.util.HashMap$Entry               221872  6212416
class [Ljava.util.HashMap$Entry;            23797   6032056
class java.lang.String                      271170  5423400
class org.hibernate.hql.ast.tree.Node       103588  4972224
class net.bull.javamelody.CounterRequest    28809   2996136
class org.hibernate.hql.ast.tree.IdentNode  23461   2205334
class java.lang.Class                       14677   2113488
class org.hibernate.hql.ast.tree.DotNode    13045   1852390
class [Ljava.lang.String;                   48506   1335600
class [Ljava.lang.Object;                   12997   1317016 


Instance Counts for All Classes (excluding platform) :

103588 instances of class org.hibernate.hql.ast.tree.Node
33366 instances of class antlr.ANTLRHashString
28809 instances of class net.bull.javamelody.CounterRequest
24436 instances of class org.apache.tomcat.util.buf.ByteChunk
23461 instances of class org.hibernate.hql.ast.tree.IdentNode
22781 instances of class org.apache.tomcat.util.buf.CharChunk
22331 instances of class org.apache.tomcat.util.buf.MessageBytes
13045 instances of class org.hibernate.hql.ast.tree.DotNode
10024 instances of class net.bull.javamelody.JRobin
9084 instances of class org.apache.catalina.loader.ResourceEntry
7931 instances of class org.hibernate.hql.ast.tree.SqlNode 

[更新2]server.xml:

<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               URIEncoding="UTF-8"
               maxThreads="150"
               minSpareThreads="25"
               maxSpareThreads="75"
               enableLookups="false"
               acceptCount="1024"
               server="unknown"
               address="public_ip"
    />

**** [UPDATE 3]ログファイルからの出力:****

    2012-06-04 06:18:24,152 [http-bio-ip-8080-exec-3500] ERROR org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/api].[Jersey REST Service]- Servlet.ser
vice() for servlet [Jersey REST Service] in context with path [/socialapi] threw exception
java.net.SocketTimeoutException: Read timed out

    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:129)
    at org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:532)
    at org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:501)
    at org.apache.coyote.http11.InternalInputBuffer$InputStreamInputBuffer.doRead(InternalInputBuffer.java:563)
    at org.apache.coyote.http11.filters.IdentityInputFilter.doRead(IdentityInputFilter.java:118)
    at org.apache.coyote.http11.AbstractInputBuffer.doRead(AbstractInputBuffer.java:326)
    at org.apache.coyote.Request.doRead(Request.java:422)

[更新4]ServletContext

ServletContextListenerは自分のアプリケーションでを使用してコントローラーをインスタンス化し、。で参照を保持しますevent.getServletContext().setAttribute。これらのコントローラーは、構成と変換(Permで88Mb)をロードします。

次に、データベースを使用するには、次を使用します。

SessionFactory sf = dbManager.getSessionFactory(DatabaseManager.DB_KEY_DEFAULT);
Session session = sf.openSession();
Transaction tx = null; 

try {
    tx = session.beginTransaction();

    //Do stuuf

    tx.commit();

} catch (Exception e){
    //Do something
} finally {
    session.close();
}
  1. これがリークの原因である可能性がありますか?
  2. 手動トランザクション/セッションを使用しないのはなぜですか?それではどのように行いますか?
4

2 に答える 2

14

このパラメータで試してください:

+XX:+HeapDumpOnOutOfMemoryError -XX:+HeapDumpPath=dump.log

また、開始メモリパラメータを低くしてみてください-Xms

次に、ダンプを調べて、問題がオブジェクトの割り当てであったかどうかを確認できます。

実行中に試してみてください

jps

これにより、すべてのJavaプロセスが出力されます。たとえばTomcatPID4444です。

jmap -dump:format=b,file=heapdump 4444

jhat heapdump

jhatの実行中にメモリが不足した場合は、メモリを追加してください。そこから、アプリケーションのヒープを検査できます。

もう1つの方法は、Hibernate統計を有効にして、それ以上オブジェクトを取得していないことを確認することです。1時間ごとの完全なガベージコレクションのように見えますが、問題にはならないはずです(そこではもっとうまくやる余地があります)。

-verbose:gc -Xloggc:/opt/tomcat/logs/gc.out -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

たとえば、GCViewerを使用して、メモリのすべてのスペース(ternured、eden、survivors、perm)を確認します。

もう1つの便利なツール:

jstack 4444 > stack.txt

これにより、pid4444を使用してJavaプロセス内で実行されているすべてのスレッドの完全なスタックトレースが取得されます。

Tomcatrootまたは別のユーザーとして開始した場合は、特権が必要であることに注意してください。

jps

権限のないプロセスは出力されないため、接続できません。

私はあなたのアプリケーションが何であるかを知らないので(そしてそれ故に私はその要件を知りません)、300万のインスタンスはたくさんのように見えます。

これによりHibernate statistics、どのクラスを最もインスタンス化するかを確認できます。

次に、eden and ternuredガベージの再収集の比率を調整する方が効率的です。

新しくインスタンス化されたオブジェクトはedenに移動します。マイナーなgcトリガーがいっぱいになると。削除されないものはサバイバースペースに行きます。これがいっぱいになると、それはternuredになります。ternuredがいっぱいになると、完全なgcが発生します。

この図(不正確です)ではString、インターン化され、メモリマップトファイル(ヒープ内にない)になるものを脇に置いておきました。最もインスタンス化するクラスを見てください。を集中的に使用すると、Stringパーマがすぐにいっぱいになる可能性があります。

そうだと思いますが、Springなどのマネージドセッションファクトリ(スタック内にある場合)を使用し、トランザクションとセッションを手動で管理することは避けてください。

オブジェクトが参照していない場合、GCでオブジェクトが削除されることに注意してください。アプリケーションでオブジェクトに到達できる限り、オブジェクトは残ります。

ServletContextListenerがコントローラーをインスタンス化し、イベントgetServletContextに格納されている場合。後で参照を完全に削除するようにしてください。参照を保持すると、オブジェクトは引き続き到達可能であるため、削除されません。

Spring-tx独自のトランザクションとセッションを管理する場合(フレームワークを使用できない場合は問題ありません)、コードのメンテナンスや、たとえば解決および改善されたバグに対処する必要があります。

私は個人的にを利用しFOSSます。ただし、もちろん、スタックを拡大できない場合もあります。

使用している場合は、トランザクションとセッションをHibernate確認しSpring-ormて管理します。Spring-txまた、を見てくださいHibernate patter Open Session In View

于 2012-06-07T14:00:04.333 に答える
2

また、Visual VM 1.3.3をダウンロードし、すべてのプラグインをインストールして、Tomcat PIDにアタッチすることをお勧めします。これにより、リアルタイムで何が起こっているかを確認できます。なぜスレッドダンプを待つのですか?また、CPU、スレッド、すべてのヒープ世代、どのオブジェクトが最も多くのメモリを消費するかなども示します。

于 2012-06-07T14:40:57.723 に答える