【最適化】マルチスレッドアクセスデータベースによるメモリリークの最適化プロセス

2884 ワード

[size=medium]本文は、http://www.blogjava.net/persister/archive/2010/01/14/309530.html
1、この会社にはデータベースプロキシがあります.データベースサーバのプロキシに使用して、ゲームサーバはsql命令を実行して、DBAgentはこのコマンドを受けて、いくつかの組織を実行した後、JDBCを呼び出してデータベース操作を実行して、結果を返します.
2、発生した問題:メモリが常に上昇しており、クライアントから要求されたスレッドは多くない(ピーク時は300ぐらいかな)、データベース上の接続数も多くない(100のような).5-6日間の実行では、基本的にメモリがなくなり、データベースの接続が得られません.彼らはとても急いでいます.このプロジェクトを受けてみます.
3、この最適化プロジェクトを受け取って、彼らのコードの一部を確認しました.接続池の書き込みに問題があり、データベース接続後のwaitは得られませんでしたが、有効なnotifyはもらえません.つまり待つだけで時間が超過します.他にも問題があります.最初はこの問題だと思いました.修正して走らせたら、結局同じです.メモリが上がってからずっと下りられなくて、最後に崩壊しました.
4、この発見によってメモリが漏れています.最初はjprofilerでテストしましたが、メモリが上がったらOut of memoryになります.そしてhashmapとlong[]のオブジェクトがとても多くて、まっすぐに下りられません.しかし、これらの相手が見つからないです.どうやって生まれたのですか?何日間も苦しめられました.たくさんの人に教えてもらいましたが、答えは得られませんでした.その後、Java起動パラメータの中にメモリパラメータが設定されていることが分かりました.100 m以上のメモリが必要です.16 Mに設定して、崩壊しないとおかしくないです.そこで128 Mに変更しました.その結果、メモリ上にピークが来て、震動しましたが、ずっと上がっていませんでした.そのプログラムは漏れていませんか?しかし、生産上はどうして漏れましたか?
5、基本的に諦めたい時、テスト環境が違っているかもしれないと思いました.彼らの生産サーバー上の仮想マシンの運行状況を見る必要があります.Javaは自分の持っているツールでjava仮想マシンの運行状況を調べました.jmapというツールは、jvmにおける実行例の個数およびインスタンスの類名を確認することができる.彼らの人にこの道具を使わせて、結果を送ってくれました.見て、びっくりしました.1位はint[]で、なんと1 Gに達しました.問題なのはcomp.mysql.jdbc.PreparedSttementの対象が6万以上に達しています.comple.mysql.jdbc.Result SetImplとjava.util.HashMap$Enttry[]も6万以上に達しました.もちろん、PreparedSttementは閉鎖されていません.
6、ソースコードを確認したら、PreparedSttementの対象は全部finallyブロックの中で閉鎖されています.どうして漏れますか?一時間探しましたが、見つけられませんでした.お風呂に入りました.お風呂に入る時にふと思いました.中にはforサイクルがあります.PreparedSttementの対象はN回の値を与えられます.前のN-1回は閉じていないじゃないですか?はい、答えを見つけました.急いで体を拭いてきて、そのコードを見つけます.[/size]

1 String[] valuesArray = value.split(";");
2 for (int i = 0 ;i < valuesArray.length;i++){
3
4 String[] valueArray = valuesArray[i].split(",");
10 ps = conn.prepareStatement(sqlbean.getSql());
11 for(int k = 0;k 12 if("s".equalsIgnoreCase(paraTypeArray[k])){
13 ps.setString(k+1,valueArray[k]);
14 }else if("i".equalsIgnoreCase(paraTypeArray[k])){
15 ps.setInt(k+1,Integer.parseInt(valueArray[k]));
16 }
17 }
18
19 rsString = "" + ps.executeUpdate();
20
21 }
[size=medium]確かに、ループのN-1個のPreparedSttementオブジェクトが閉じられていないため、漏れが発生しました.解決策はつまり
ps=conn.prepareSttement(sql bean.get Sql();
forサイクルの外に移動すれば大丈夫です.でも、このコードからも分かるように、書いたのも腐っています.これはどうして置きますか?
ループの中には、言葉自体に問題があります.それに関わらず、問題を解決すればいいです.
ほとんど一晩中興奮しました.翌日彼らの人に話してみます.彼らはN回循環すると言っています.ただの値ではないです.問題は解決されたのではないですか?Great
7、テストを実行させましょう.初日の夜9時以降は、メモリが非常に安定しています.問題はすっかり解決した.
今回の最適化プロジェクトをまとめます.
Java仮想マシンに対する認識が高まった.java性能テストツールにもっと慣れました.eclipseと統合できます.とても便利です.[/size]