汎用シリアル化を使用した Fastjson はメモリ リークを引き起こす
1. 背景
ある朝、実稼働環境のアラーム グループに応答時間が 1 秒を超える低速インターフェイスが多数出現し、アプリケーション ログで多くのインターフェイスがタイムアウトしてパンクしていることがわかりました (応答時間 >= 5 秒)。
このうち、多くのインターフェイスの SQL はインデックスを使用でき、DBA が確認したところ、データベースに問題はありませんでした。
ホスト上で top コマンドを使用して CPU 使用率を確認すると、例外があることがわかります。一部のホストの CPU は約 50% であり、ホストの 1 つの CPU は時々 300% まで上昇し、継続します。
2. CPU使用率の調査
1. CPU 消費量が最も高いプロセスの PID を確認します 41594
シェルコマンド: top -c
2. Pid に従って、CPU を最も多く消費するスレッド番号 41600 を見つけます。
シェルコマンド: top -Hp 41594
3. これは 10 進数のデータを 16 進数に変換したもので、a280 となります。
シェル コマンド: printf "%x\n" 41600
4. PIDのスタック情報をエクスポートする
シェルコマンド: jstack -l 41594 > 41594.stack
5. 41594.stack でスレッド番号のキーワード「a280」を検索し、次の行を見つけます。
「GC タスク スレッド #4 (ParallelGC)」 os_prio=0 tid=0x00007f41f8026800 nid=0xa280 実行可能
上位 5 つのスレッド番号を検索したところ、すべて GC スレッドであることがわかり、ヒープ メモリに問題があることがわかりました。
3. 監視状況
Grafana モニタリングを通じて JVM メモリと GC ステータスをチェックし、ヒープ メモリが基本的にいっぱいであることを確認します。
GC 回数と時間が大幅に増加
この場合、分析用にメモリ スナップショットを取得し、メモリ スナップショットをエクスポートする必要があります。
シェルコマンド:jmap -dump:format=b,file=dump-20210809.hprof 41594
ファイルを圧縮してからダウンロードする
シェルコマンド:tar -czf dump-20210809.hprof.tar.gz dump-20210809.hprof
シェルコマンド: sz dump-20210809.hprof.tar.gz
3、ダンプ分析
MemoryAnalyzer (MAT) ツールを使用してダンプ ファイルを分析すると、1.4G のメモリがクラス com.alibaba.fastjson.parser.ParserConfig によって占有されていることがわかります。
list_objects ビューを展開して表示すると、com.alibaba.fastjson.util.IdentityHashMap で 1.4G が消費されていることがわかります。
インターネット上の関連情報を検索したところ、関連する問題もあることがわかりました: fastjson 逆シリアル化の不適切な使用によりメモリ リークが発生する - liqipeng - 博客园
コード内でキーワード「 ParameterizedTypeImpl 」を検索すると、確かに便利です。
これまでのところ、情報どおりに問題が特定されています。
次のステップでは、この問題を再現し、このコードを継続的に実行するループを作成し、100,000 回ループしてから、ヒープ メモリをダンプして確認します。
結果は次のとおりです。346M はクラス com.alibaba.fastjson.parser.ParserConfig によって占められています。
com.alibaba.fastjson.util.IdentityHashMap のパフォーマンスも安定しています
オンライン情報には関連する解決策も記載されています。ここでは「方法 2」を使用します。
次に、ヒープ メモリのスナップショットをダンプすると、com.alibaba.fastjson.parser.ParserConfig がビューに表示されなくなります。