Log ファイルから有用な情報を抽出することは、Java アプリケーションの成功に不可欠です。 ログ データは、アプリケーションのパフォーマンス、安定性、およびユーザビリティに対する貴重な洞察を与えてくれます。
ログ データの分析は退屈に思えるかもしれませんが、その必要はありません。 ログ データを読み取り、解析し、統合するためのさまざまなツールがあります。 grep、uniq、および sort などの基本的なコマンド ライン ツールは、ログ ファイルから有用な情報を結合して抽出することができます。 LogstashやFluentdなどのより高度なログパーサは、ログから重要なデータを抽出して、検索しやすいトークンにすることができます。 SolarWinds® Loggly® などのクラウドベースのログ サービスは、ログ データを保存し、高度な分析機能を提供するので、ログを自分で管理する必要はありません。
このセクションでは、アプリケーションを改善する目的でログを分析するいくつかの方法とツールを探ります。 ほとんどのログ記録フレームワークは、例外の種類、例外メッセージ、および例外が発生したメソッドを記録します。 Log4j を使用して、例外のログは次のいずれかに似ています。
09:54:44.565 ERROR Log4jTest.MathClass - java.lang.ArithmeticException: / by zero10:00:10.157 ERROR Log4jTest.Log4jTest - java.io.FileNotFoundException: myFile (No such file or directory)10:00:10.157 ERROR Log4jTest.Log4jTest - java.io.FileNotFoundException: newFile (No such file or directory)
If your output includes stack traces, see the Parsing Multiline Stack Traces section of this guide.
人気のある GNU ツール grep を使った簡単な例で始めましょう。 次に、ログ管理ツールがどのようにそれをさらに簡単にするかを紹介します。
- Finding Exceptions by Type Using Grep
- Grep によるクラス別の例外の検索
- Using a Log Management Solution
- Debugging Production Problems
- その他の量産デバッグ ツール
- OverOps
- BTrace
- jhsdb
- Tracing Transactions
- Tracing Unique IDs
- Tracing Methods
- Log4jのトレース・メソッド
- Tracing Methods in SLF4J
- Managing Memory Usage
- Garbage Collection
- Memory Leaks
- その他のリソース
- See it.Of.Pirates
- See it.Of.Pirates -Guide to GARB
Finding Exceptions by Type Using Grep
The following Unix command will find exceptions, extract the exception type, and count the number of occurrence.grep is a popular command-line tool that perform pattern matching, while uniq and sort, respectively group and sort the results:
$ grep -o "\w*Exception" myLog.log | sort -r | uniq -c
This example, the regular expression \w*Exception
matches any words that ends with “Exception “この例で、正規表現は “例外 “で終わるすべての単語にマッチします。 -o
フラグは、検索文字列に一致する部分のみを出力するよう grep に指示します。 sort -r
は結果を逆順にソートし、uniq -c
は結果をグループ化して出現回数をカウントする。
2 FileNotFoundException1 ArithmeticException
また、grep を使用して、これらの例外の各特定インスタンスのログを検索することができます。
$ grep ArithmeticException myLog.log09:54:44.565 ERROR Log4jTest.Log4jTest - java.lang.ArithmeticException: / by zero
これは、検索文字列 ArithmeticException
のインスタンスを含む各行を返し、検索文字列自体を出力で強調表示します。
Grep によるクラス別の例外の検索
また、例外が発生したクラスによって検索することができます。 grep は、特定の文字(この例ではハイフンを使用していますが、エントリに固有の文字であれば何でも使用できます)が続く単語を検索して、クラス名を抽出します。 この文字は必須ではありませんが、ログイベント内のクラス名を特定するのに役立ちます。 OR 演算子 (| で表記) を使用すると、grep は文字列 “Exception” を含む単語を検索して、例外の名前も抽出します。
sed は、grep からの出力をフォーマットするために使用できる別のコマンドライン ユーティリティです。 この例では、sed は出力から特殊文字を削除し、改行文字も削除します。
$ grep -o "w* -|\w*Exception" myLog.log | sed 'N; s/ -n/ /' | sort -r | uniq -c
その結果、主要な問題領域に近づくことができました:
2 Log4jTest FileNotFoundException1 MathClass ArithmeticException
これらの結果を使用して、特定のクラスで発生する問題についての詳細を見つけるために grep を使用できます。 たとえば、次のコマンドは、MathClass
クラスで発生した例外を検索します。
$ grep -e "MathClass.*Exception" myLog.log09:54:44.565 ERROR Log4jtest.MathClass - java.lang.ArithmeticException: / by zero
Using a Log Management Solution
Most log management solutions offers ways to group and search log entries based on log type, message content, class, method, and thread. ログがすでに解析され保存されている場合、多くのソリューションでは、例外をグラフ化し、発生数で並べ替えることができます。 これはLogglyではポイント&クリック操作なので、複雑なgrepコマンドを記憶する必要はありません。 また、Logglyはログレコードのインデックスを作成するため、検索やカウントがgrepよりもはるかに高速になります。 たとえば、フィールド エクスプローラーを使用して例外のリストとその頻度を確認し、例外をクリックして関連するすべてのログを表示できます。
Loggly Field Explorer を使用して例外タイプでログをすばやく検索する。
また、Loggly は、grep からのテキスト ベースの出力よりも有益な可視化ツールを提供します。 このようなグラフは、開発スプリントや新しいリリース後のパッチのリソースの優先順位付けに役立ちます。
Loggly で例外を頻度でグラフ化する。
Debugging Production Problems
生産上の問題に関しては、時間が非常に重要です。 アプリケーションに重大なエラーが発生すると、ユーザーが不満を抱くだけでなく、売り上げが低下し、アプリケーションやサービスに対する信頼が失われます。
ほとんどの場合、問題を解決するには、次の 3 つの重要なステップに分けることができます。 スクリーンショット、クラッシュ レポート、ログ、リンク (Web サービスの場合) など、可能な限り多くの情報を収集し、潜在的な原因を絞り込むのに役立てます。 問題が発生したユーザーは、問題がいつ、プログラムのどこで発生したか、問題に至るまでの行動、動作環境、問題発生前後のプログラムからの奇妙で異常な動作など、事象に関する詳細な情報を提供する必要があります。 アプリケーションがホストされたサービスである場合、Web サーバーとアプリケーション サーバーからログの取得を開始します。 アプリケーションが分散型ソフトウェアパッケージである場合、バグレポートにログデータを含めるようにユーザーに依頼します。 代わりに、アプリケーションがログ イベントを集中ログ サーバーに送信する場合、ログはすぐに利用可能になります。
問題に関する妥当な量のデータがあれば、コードでそれを追跡し始めることができます。 開発環境でバグを再現することは、その存在を検証する最も簡単な方法の 1 つですが、時間がかかり、すべてのケースでうまくいくとは限りません。 ログの完全なセットを持つことで、問題のソースに直接たどり着き、時間とフラストレーションを節約することができます。 選択したログ管理ツールを使用して、ユーザー名、セッション ID、またはメッセージ テキストなどの固有のデータ トークンを検索することにより、ログ エントリのより少ない範囲に検索を絞り込むことができます。 Web サイトにリモートでログインするための Web ベースのインターフェイスがあると想像してください。 Web ページには、ユーザー名とパスワードを使用して基本認証を実行するログイン画面があります。 ユーザーから、Web サイトにログインできないとの報告がありました。
A sample website reporting an error after a login attempt.
このメッセージからは、ログの深刻度の一般的な表示以外に多くの情報を得ることができません。 ログ マネージャーでレベルまたはメッセージに「深刻」を含むエントリを検索すると、何百もの結果が得られ、そのどれもが目下の問題に関連しているという保証はありません。 幸いなことに、私たちの Logger
は、エラーを経験したユーザーのユーザー名も記録していたので、「admin」ユーザー名でフィルターすることができます。
Loggly で Java 例外を表示する
掘り下げてみると、エラーの原因は見つからないか無効なテーブルであることがわかります。 これは、誤って削除されたか、データベースが破損していることを示すので、深刻な問題です。
ERROR: Exception for user admincom.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'test_schema.users' doesn't exist...com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1651) at TestApplication.Test.doPost(Test.java:33) at javax.servlet.http.HttpServlet.service(HttpServlet.java:646) at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) at...
スタック トレースを調べると、Test.java の 33 行目でサービスが失敗したことが分かります。 この行は、test_schema.users テーブルからユーザーに関するデータを取得する SQL 文で構成されています。
rs = stmt.executeQuery("SELECT * FROM test_schema.users WHERE username = " + username + " AND Password = " + password);
SQL フロントエンドでこのクエリを実行しようとすると、「test_schema.users」テーブルが存在しないことが判明します。 しかし、データベースには “test_schema.user” テーブルが存在します。 ある時点で、開発者が誤って間違ったテーブル名を入力し、修正したフォームを本番環境にプッシュした可能性があります。 SolarWinds Loggly を使用すると、アプリケーション スタックを通じて、複数のログ イベントにわたってエラーをトレースし、さらに GitHub で関連するコード行をピンポイントで特定することにより、問題の根本原因をデバッグして見つけることができます。 私たちのログインの例は、比較的簡単に解決できる大げさなケースでしたが、アプリケーションのさまざまな領域に根ざしたより複雑なバグに遭遇する可能性があります。 手軽な修正に飛びつく前に、その変更がアプリケーションにどのような影響を与えるかを慎重に検討しましょう。 これは本当にその問題に対する最善の解決策なのでしょうか? その変更が他のコンポーネントと干渉する可能性はありませんか? この修正によって、将来的に新しい修正や機能を導入することが難しくなりませんか?
たとえば、2 人の異なるユーザーが、同じユーザー名とパスワードで 2 つの別々のアカウントを作成した場合、どうなるでしょうか? すべてのユーザーに対して一意のユーザー名を強制することができますが、データベース構造、認証コード、および既存のユーザーベースにどのような影響を与えるでしょうか。 電子メールアドレスのような新しいユニークなフィールドを追加して、それを必須にすることもできますが、現在のユーザーの中に電子メールアドレスを提供していない人がいたらどうでしょうか? また、複数のアカウントでメールアドレスを共有している場合はどうでしょうか。 これらの新しいルールは、登録、検索、および管理ページにどのような影響を与えるのでしょうか。 企業環境では、あなたのコードは、他の開発者によるレビュー、コード ベースへの統合、ビルド、QA によるテスト、ステージング、さらにいくつかのステップを経てから本番環境に投入される必要があります。 あなたの会社では、重要なバグや時間的制約のあるバグに対して、特定のプロトコルを設けている場合があります。 解決策が見つかったら、その解決策を文書に記載し、問題に対する合理的な回避策も含めてください。 この方法では、顧客は製品を引き続き使用でき、サポート チームは、修正が本番環境に適用される間、重複するバグ報告の数を減らすことができます。
修正を展開した後、問題が解決されたことを確認するために本番アプリケーションの監視を継続します。 たとえば、上記の例のデータベースの問題に対する修正を展開した後、「Table ‘test_schema.users’ doesn’t exist」のイベントはもう表示されないはずです。 エラーが続いたり、新しいエラーが発生したりする場合は、修正がうまくいかなかったということです。 理想的には、次のスクリーンショットに示すようなパターンが見られ、パッチを展開した直後にエラーの数がゼロになることです。
その他の量産デバッグ ツール
ログは、アプリケーションのトラブルシューティングおよびデバッグのための試行錯誤の方法ですが、これらのツールは、アプリケーションがどのように動作するかについてより多くの洞察を得るのに役立ちます。 jdb を使用すると、新しい Java 仮想マシン (JVM) が作成され、実行中のプログラムに影響を与えることなくクラスをデバッグすることができます。 また、javaコマンドに以下のパラメータを追加することで、実行中のアプリケーションのデバッグにjdbを使用することができます:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n
JVMが起動すると、jdb接続を受信するためのポート番号が割り振られます。 次に、jdb -attach:
$ jdb -attach
を使用して、実行中のJVMインスタンスにアタッチすることができます。 このシナリオでは、アクティブなスレッドを一時停止する可能性があるため、ブレークポイントを使用することに注意してください。 これは、たとえば、デバッグ中に顧客がアプリケーションを使用している場合、結果をもたらす可能性があります。 詳細については、Java の jdb.
OverOps
OverOps は、アプリケーションの監視、コードの分析、および問題の検出のためのツール群です。 実行中のアプリケーションによって生成された出力に依存するロギング ソフトウェアとは異なり、OverOps は Java 仮想マシンに直接接続して、アプリケーションのコード ベースをマッピングし、変数を読み取り、そしてエラーを記録します。 これにより、アプリケーションのロギング・フレームワークよりも多くのエラーを検出し、より多くのデータを記録することができます。 OverOpsはSaaS(Software as a Service)モデルを採用しており、メトリクスはOverOpsのクラウドサーバーに収集・保存されます。 しかし、オンプレミスで展開することも可能です。 どちらの場合でも、Web ベースのインターフェイスを使用してデータを表示できます。
BTrace
BTrace は、クラス名からエラーまで、アプリケーションのすべての側面を監視できるトレース ツールです。 BTrace は、BTrace がアプリケーションを監視する場所と方法を指定するアノテーションの使用を含む、アスペクト指向のプログラミング アプローチを使用します。 たとえば、次の BTrace スクリプトは、javax.swing
パッケージへの各々およびすべての呼び出しを監視し、ログに記録します。
import com.sun.btrace.annotations.*;import static com.sun.btrace.BTraceUtils.*; @BTrace public class AllMethods { @OnMethod( clazz="/javax\.swing\..*/", method="/.*/" ) public static void m(@ProbeClassName String probeClass, @ProbeMethodName String probeMethod) { print(Strings.strcat("entered ", probeClass)); println(Strings.strcat(".", probeMethod)); }}
BTrace に関する詳細については、BTrace GitHub リポジトリおよび Wiki を参照してください。 アプリケーションのライフタイム中に行われた個々の変更を記録し、任意の時点でアプリケーションの状態を再現することができます。 記録はファイルに保存され、テスト用に本番マシンから開発マシンへ実行履歴を簡単に転送できます。
Chrononは、リモートでJavaアプリケーションを記録できるChronon Recording Server、アプリケーション内にレコーダーを埋め込むEmbedded Chronon、記録を再生できるTime Travelling Debuggerで構成されます。
jhsdb
jhsdb (Java HotSpot Debugger) は、OpenJDK と Oracle JDK の両方で提供されるデフォルト JVM をデバッグ、分析、およびプロファイリングするためのツール群である。 jhsdbは、実行中のJavaプロセスにアタッチし、スタックトレースのスナップショットを取り、クラッシュしたJVMを分析することもできます。 ヒープ、コードキャッシュ、ガベージコレクション統計などにアクセスするために使用することができます。 詳細については、jhsdb ドキュメント ページを参照してください。
Tracing Transactions
問題が発生した場合、問題がどこで始まり、それがアプリケーションの残りの部分にどのように影響したかを知ることは重要です。 これは、モノリシックなアプリケーションでは十分に困難ですが、単一のリクエストが何十ものサービスに当たる可能性のある、分散サービス指向アーキテクチャではさらに困難になります。 どのサービスにエラーの根本原因があるのか、またそれが他のサービスにどのような影響を与えたのか、常に明らかとは限りません。 トレースは、アプリケーションの実行パスを追跡し、問題の正確な原因を突き止めるために必要なデータを提供します。
ガイドの「生産上の問題のデバッグ」のセクションでは、無効なデータベース テーブルのためにユーザーが Web アプリケーションにログインできない例を説明しました。 このセクションでは、トランザクションのトレースが問題の解決にどのように中心的な役割を果たしたかを紹介します。
Tracing Unique IDs
一連のログ イベントをトレースするには、関連するログを一意に識別する何らかの方法が必要です。 マルチユーザー環境では、何百もの同一のログが生成され、タイムスタンプまたは Logger
に基づいて検索することが困難になります。 より簡単な解決策は、関連するログ・エントリに一意の識別子を含めることです。 この識別子は、ユーザー名、セッションID、APIキー、またはUniversally Unique Identifier (UUID)である可能性があります。 幸いなことに、ThreadContext はこの作業に完全に適しています。
Debugging Production Problems の例では、Tomcat サーブレットでホストされ、MySQL データベースに接続する Web ベースのユーザー インターフェイスを持っていました。 ユーザーは Web ページに資格情報を入力し、送信を押した後、サーブレットはデータベースに格納されている資格情報と比較するクエリを実行しました。 ユーザーが認証に成功すると、メインページにリダイレクトされる。 エラーが発生した場合、エラーの詳細が記録され、ユーザーには一般的なメッセージが表示されました。
私たちは、ログ メッセージにユーザーのユーザー名を含めることにより、この問題をデバッグすることができました。 これにより、admin ユーザーに関連するログ イベントをすばやく検索することができました。 この同じ例から構築すると、ThreadContext.put()
を使用してユーザー名を Logger
にマップすることができます。 ユーザーが認証情報を送信すると、サーブレットは doPost()
メソッドに入り、ThreadContext にユーザーのユーザー名を追加します:
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {ThreadContext.put("username", request.getParameter("username"));logger.info("Entering doPost().");...}
パターン %p : %m%n
で Log4j を使用すると、次のエントリーになります:
INFO : Entering doPost().
私たちは MySQL データベースにアクセスする、 doPost メソッドを残して、他の動作を実行する、同様のイベントを加えることができます。 この方法では、ユーザーが例外をトリガーする場合、例外が発生したときにユーザーが何をしていたかを正確に知ることができます。
Tracing Methods
多くのロギング フレームワークは、アプリケーションの実行パスをトレースするネイティブ メソッドを提供します。 これらのメソッドはフレームワークによって若干異なりますが、同じ一般的な形式に従っています。
-
traceEntry()
はメソッドの開始をマークします。 オブジェクトを返すメソッドでは、オブジェクトを返すと同時にreturn logger.exit(object)
でイベントを記録することができます。 -
throwing()
はRuntimeException
のように処理されそうにない例外をマークします。 -
catching()
は再スローしないであろう例外をマークします。
Log4j, Logback および java.util.logging
に関する Logger documentation で、これらのメソッドのフレームワークに固有の情報を見ることができます。
Log4jのトレース・メソッド
Log4jを使った例として、私たちのサーブレットでLogger.info()メソッドをトレース・メソッドと置き換えます。
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { logger.entry(); ... logger.exit();}
また、クラス名、メソッド、行番号を表示するためにAppender's PatternLayout
を変更します (%class
, %M
, %line
変換パターン).
<PatternLayout pattern="%p %class %M %line: %m%n" />
トレースメソッドはTRACE
レベルでイベントを記録します、これはLogger's
レベルをDEBUG
からTRACE
へと変更しなければならないということを意味しています。 さもなければ、ログ・メッセージは抑制されます。
<Loggers> <Root level="trace"> <AppenderRef ref="Console"/> </Root></Loggers> TRACE DatabaseApplication.Login doPost 26: entry...TRACE DatabaseApplication.Login doPost 59: exit
Tracing メソッドはまた、独自の Markers
を提供します。 たとえば、Logger.entry()
と Logger.exit()
メソッドはそれぞれ ENTER
と EXIT
を表示します。
ENTER 14:47:41.074 TRACE DatabaseApplication.Login - EnterEXIT 14:47:41.251 TRACE DatabaseApplication.Login - Exit
Tracing Methods in SLF4J
SLF4J ユーザーはログイベントのトレースに MDC を利用することが可能です。 Log4j と同様に、MDC 値は %X 変換パターンを使用して Appender で使用できます。
SLF4J も XLogger
(Extended Logger) クラスを通して entry()
, exit()
, throwing()
, catching()
メソッドを提供しています。
package DatabaseApplication;import org.slf4j.Logger;import org.slf4j.LoggerFactory; import org.slf4j.ext.XLogger;import org.slf4j.ext.XLoggerFactory; public class Login extends HTTPServlet { final static XLogger xlogger = XLoggerFactory.getXLogger(Login.class.getName()); final static Logger logger = LoggerFactory.getLogger(Login.class.getName()); @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { xlogger.entry(); .. xlogger.exit(); }}
logback.xml に %class と %line 変換パターンを追加します。
<configuration> <appender name="Console" class="ch.qos.Logback.core.ConsoleAppender"> <encoder> <pattern>%-5level %class{36} %M %L: %msg%xEx%n</pattern> </encoder> </appender> <root level="trace"> ... </root></configuration>
結果として得られるログエントリーは Log4j で作成されるものと同じです。
Managing Memory Usage
Javaなどの高度な言語では、メモリ管理はしばしば見落とされています。 最近のデバイスの平均的なメモリ量は増加していますが、高いメモリ使用量はアプリケーションの安定性とパフォーマンスに大きな影響を与える可能性があります。 Java仮想マシンがオペレーティングシステムからメモリを割り当てられなくなると、プログラムが終了してクラッシュする可能性があります。 メモリを管理する方法を知っていれば、アプリケーションのサイズが大きくなっても問題を防ぐことができます。
たとえば、1から始まる数字のセットを保存したいとします。 ユーザーは上限を提供し、プログラムは「1」からその上限までの各整数を保存します。
import java.util.Scanner;...System.out.print("Please enter the maximum size of the array: ");Scanner scanner = new Scanner(System.in);int limit = scanner.nextInt(); ArrayList intArray = new ArrayList(); int count = 1;while (count <= limit) { intArray.add(count);}
ループの中でcount
がインクリメントしないことに気づいたかもしれません。 これは大きな問題で、ユーザーがゼロより大きい数を入力すると、JVM が利用可能なメモリをすべて使用してプログラムがクラッシュするまで、配列は増え続けます。
Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceat java.util.Arrays.copyOf(Arrays.java:2245)at java.util.Arrays.copyOf(Arrays.java:2219)at java.util.ArrayList.grow(ArrayList.java:242)at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:216)at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:208)at java.util.ArrayList.add(ArrayList.java:440)at MemoryTest.main(MemoryTest.java:10)
Garbage Collection
メモリ使用を減らすために、Java 仮想マシンはガベージ コレクションとして知られる定期的なクリーンアップ プロセスを実行します。 ガベージコレクションは、もはや使用されていないメモリブロックを探し出し、それらを再利用できるようにします。 以下の資料では、Javaのガベージコレクションプロセスをより詳しく説明しています。
- Java ガーベッジコレクションの基本 (Oracle)
- HotSpot 仮想マシン ガーベッジコレクション チューニング ガイド (Oracle)
- Understanding G1 GC Logs (Poonam Bajaj)
- Garbage Collection Tuning Guide (Atlassian)
ガーベッジコレクターは、パフォーマンス プロファイリングのアプリケーションに有用である診断情報を作成します。 アプリケーションの起動時に JVM に -Xlog:gc を渡すことで、この情報を記録できます。 各実行後、ガベージコレクタは、ガベージコレクションプロセスに関する統計情報をUnified JVM Loggingフォーマットで表示します。 以下はその例です。
Using G1 Periodic GC disabled GC(0) Pause Young (Normal) (G1 Evacuation Pause) 7M->1M(64M) 8.450ms
Using G1
は、どのガベージコレクション方式が使用されているのかを述べています。 ガベージファースト(G1)コレクターは、多くの場合、大量のRAMを持つマルチプロセッサ・コンピュータでデフォルトで有効になっています。 Periodic GC disabled
はガベージコレクションプロセスが繰り返されないことを示す。 3行目は、オブジェクトがまだ使用されているかどうかに基づいてメモリ領域間でコピーされる避難一時停止であることを告げている。 Pause Young
は、このプロセスが新しいオブジェクトが割り当てられる若い世代を掃除したことを告げています。 その結果、若い世代のオブジェクトによる総メモリ使用量は、割り当てられた 64M のうち 7M から 1M に減少し、プロセスは 8.450ms
.
ガベージコレクタがコンソールに診断情報を出力するため、割り当てられたメモリ量(ヒープサイズ)が時間と共に増加し続けていることを確認できます。 単純化するために CPU 時間を削除します。
$ java -Xlog:gc MemoryLeakDemo Using G1 Periodic GC disabled GC(0) Pause Young (Concurrent Start) (G1 Humongous Allocation) 25M->23M(64M) 4.372ms GC(1) Concurrent Cycle GC(1) Pause Remark 50M->34M(64M) 0.250ms GC(1) Pause Cleanup 94M->94M(124M) 0.057ms GC(1) Concurrent Cycle 169.695ms GC(2) Pause Young (Concurrent Start) (G1 Humongous Allocation) 94M->94M(124M) 3.738ms GC(3) Concurrent Cycle...
Chart showing a gradual increase in JVM heap usage over time.
各エントリーに -XX:+PrintGCDateStamps
および -XX:+PrintGCTimeStamps
でタイムスタンプを追加することができます。 また、アプリケーションを開始するときに JVM に-Xlog:gc:file
: を渡すことにより、ガベージコレクタの出力をファイルに記録できます。
rsyslogでログファイルを監視する場合、ログを集中ログシステムに転送でき、そこでほぼリアルタイムの解析の準備ができます。 Loggly のタイムライン グラフは次のようなものです。 これは、ヒープ サイズの合計と、ガベージコレクターの実行前と実行後のヒープ サイズを示します。
Memory Leaks
メモリ リークは、プログラムが解放できるよりも速くメモリを割り当てている状況です。 メモリ リークを検出する最も簡単な方法は、プログラムが応答しなくなる、不安定になる、または OutOfMemoryErrors
を引き起こすときです。 Java では、メモリの使用が増えると Full GC
コレクションのインスタンスが増えます。
Garbage Collector の出力とメモリ リークの特定について、Java ドキュメントの Troubleshoot Memory Leaks の章で詳しく説明します。
その他のリソース
Cut Debugging Time Without Write a Single Line of Code (Loggly) – Guide to use Takipi
The Ultimate Guide: 5 Methods for Debugging Production Servers at Scale (High Scalability)-Tools and techniques for debugging production problems
Memory Management
Garbage Collection Tuning Guide (Oracle)-Guide to understanding and fine-tuning Java’s garbage collection
Understanding Java Garbage Collection (CUBRID Blog)-Gurb
See it.Of.Pirates
Garriage Collection
-Guide to Understanding the Java Garbage Collection
-Guide to GARB
-Guide to GARB
See it.Of.Pirates -Guide to GARB
何が問題なのかを知る
無料トライアル開始
.