JVMのプロファイリング
JVMをプロファイリングするには、JProfilerのプロファイリングエージェントをJVMにロードする必要があります。これには2つの方法があります:
起動スクリプトで-agentpath
VMパラメータを指定するか、すでに実行中のJVMにエージェントをロードするためにattach APIを使用します。
JProfilerは両方のモードをサポートしています。VMパラメータを追加する方法はプロファイリングの推奨方法であり、統合ウィザード、IDEプラグイン、およびJProfiler内からJVMを起動するセッション設定で使用されます。 アタッチはローカルでもSSHを介してリモートでも動作します。
-agentpath VMパラメータ
プロファイリングエージェントをロードするVMパラメータがどのように構成されているかを理解することは有用です。-agentpath
は、JVMTIインターフェースを使用する任意のネイティブライブラリをロードするためにJVMが提供する一般的なVMパラメータです。
プロファイリングインターフェースJVMTIはネイティブインターフェースであるため、プロファイリングエージェントはネイティブライブラリでなければなりません。これは、
明示的にサポートされているプラットフォームでのみプロファイリングできることを意味します。
32ビットと64ビットのJVMも異なるネイティブライブラリを必要とします。
一方、Javaエージェントは-javaagent
VMパラメータでロードされ、限られた機能セットにのみアクセスできます。
-agentpath:
の後には、ネイティブライブラリへのフルパス名が追加されます。プラットフォーム固有のライブラリ名のみを指定する
-agentlib:
という同等のパラメータがありますが、その場合はライブラリがライブラリパスに含まれていることを確認する必要があります。
ライブラリへのパスの後に等号を追加し、カンマで区切ってエージェントにオプションを渡すことができます。たとえば、Linuxでは、全体のパラメータは次のようになります:
-agentpath:/opt/jprofiler15/bin/linux-x64/libjprofilerti.so=port=8849,nowait
最初の等号はパス名をパラメータから分離し、2番目の等号はパラメータport=8849
の一部です。この一般的なパラメータは、
プロファイリングエージェントがJProfiler GUIからの接続をリッスンするポートを定義します。8849は実際にはデフォルトのポートなので、そのパラメータを省略することもできます。
同じマシンで複数のJVMをプロファイリングしたい場合は、異なるポートを割り当てる必要があります。
IDEプラグインとローカルで起動されたセッションはこのポートを自動的に割り当てますが、統合ウィザードではポートを明示的に選択する必要があります。
2番目のパラメータnowait
は、プロファイリングエージェントにJProfiler GUIが接続するまでJVMを起動時にブロックしないように指示します。
起動時にブロックするのがデフォルトです。なぜなら、プロファイリングエージェントはコマンドラインパラメータとしてプロファイリング設定を受け取るのではなく、
JProfiler GUIまたは代替として設定ファイルから受け取るからです。コマンドラインパラメータはプロファイリングエージェントをブートストラップするためだけのもので、
どのように開始するかを指示し、デバッグフラグを渡すためのものです。
特定の状況下では、起動時にプロファイリング設定を設定することが必要であり、 これを達成するためにいくつかの手作業が必要になる場合があります。
デフォルトでは、JProfilerエージェントは通信ソケットをループバックインターフェースにバインドします。特定のインターフェースを選択するために
address=[IP address]
オプションを追加するか、通信ソケットをすべての利用可能なネットワークインターフェースにバインドするために
address=0.0.0.0
を追加することができます。これは、Dockerコンテナからプロファイリングポートを公開したい場合に必要になることがあります。
ローカルで起動されたセッション
IDEの「実行構成」と同様に、JProfilerでローカルで起動されたセッションを直接構成できます。クラスパス、メインクラス、作業ディレクトリ、VMパラメータと引数を指定し、 JProfilerがセッションを起動します。JProfilerに付属するすべてのデモセッションはローカルで起動されたセッションです。
特別な起動モードは「Web Start」で、JNLPファイルのURLを選択し、JProfilerがそれをプロファイリングするためのJVMを起動します。この機能は OpenWebStartをサポートし、Java 9以前のOracle JREのレガシーWebStartはサポートされていません。
ローカルで起動されたセッションは、メインメニューからSession→Conversion
Wizardsを呼び出すことで変換ウィザードを使用してスタンドアロンセッションに変換できます。
Convert Application Session to Remoteは単に開始スクリプトを作成し、-agentpath
VMパラメータをJava呼び出しに挿入します。
Convert Application Session to Offlineはoffline
profiling
のための開始スクリプトを作成し、設定が起動時にロードされ、
JProfiler GUIが必要ありません。
Convert Application Session to Redistributed Sessionは同じことを行いますが、プロファイリングエージェントと設定ファイルを含むディレクトリ
jprofiler_redist
をその隣に作成し、JProfilerがインストールされていない別のマシンにそれを送信できます。
プロファイリングするアプリケーションを自分で開発している場合は、起動されたセッションの代わりにIDE integration
を使用することを検討してください。
それはより便利で、より良いソースコードナビゲーションを提供します。アプリケーションを自分で開発していないが、すでに開始スクリプトを持っている場合は、
リモート統合ウィザードを使用することを検討してください。それはJava呼び出しに追加する必要がある正確なVMパラメータを教えてくれます。
統合ウィザード
JProfilerの統合ウィザードは、スタートスクリプトや設定ファイルをプログラム的に変更して追加のVMパラメータを含めることができる多くの有名なサードパーティ製コンテナを処理します。 一部の製品では、VMパラメータを引数として渡すか、環境変数を介して渡す開始スクリプトを生成できます。
すべての場合において、サードパーティ製品の特定のファイルを見つける必要があるため、JProfilerが変更を行うために必要なコンテキストを持つことができます。 一部の一般的なウィザードは、プロファイリングを有効にするために何をする必要があるかについての指示を提供するだけです。
各統合ウィザードの最初のステップは、ローカルマシンでプロファイリングするか、リモートマシンでプロファイリングするかの選択です。ローカルマシンの場合、 JProfilerはすでにプラットフォーム、JProfilerがインストールされている場所、および設定ファイルがどこにあるかを知っているため、提供する情報が少なくて済みます。
重要な決定は、上記で説明した「起動モード」です。デフォルトでは、プロファイリング設定は起動時にJProfiler UIから送信されますが、JVMをすぐに起動させるように プロファイリングエージェントに指示することもできます。後者の場合、プロファイリング設定はJProfiler GUIが接続されたときに適用されます。
しかし、プロファイリング設定を含む設定ファイルを指定することもでき、これははるかに効率的です。これはConfig synchronizationステップで行われます。 この場合の主な問題は、ローカルでプロファイリング設定を編集するたびに設定ファイルをリモート側と同期する必要があることです。 最もエレガントな方法は、Remote addressステップでSSHを介してリモートマシンに接続し、設定ファイルをSSH経由で自動的に転送できるようにすることです。
統合ウィザードの最後に、プロファイリングを開始するセッションが作成され、非一般的なケースではサードパーティ製品(アプリケーションサーバーなど)も開始されます。
外部開始スクリプトは、セッション設定ダイアログのApplication settingsタブのExecute start scriptおよびExecute stop script オプションで処理され、URLはOpen browser with URLチェックボックスを選択することで表示できます。ここでは、リモートマシンのアドレスと設定同期オプションを変更することもできます。
統合ウィザードはすべて、プロファイリングされるJVMがリモートマシンで実行されている場合を処理します。しかし、設定ファイルや開始スクリプトを変更する必要がある場合は、
それをローカルマシンにコピーし、変更されたバージョンをリモートマシンに戻す必要があります。コマンドラインツールを
リモートマシンで直接実行し、その場で変更を行う方が便利かもしれません。
jpintegrate
はJProfilerの完全なインストールを必要とし、JProfiler GUIと同じJRE要件があります。
jpintegrate
リモートプロファイリングセッションを開始する際にエラーが発生した場合は、問題を解決するために取るべき手順のチェックリストを含む トラブルシューティングガイドを参照してください。
IDE統合
アプリケーションをプロファイリングする最も便利な方法は、IDE統合を通じて行うことです。開発中に通常IDEからアプリケーションを起動する場合、 IDEはすでに必要な情報をすべて持っており、JProfilerプラグインはプロファイリング用のVMパラメータを追加し、必要に応じてJProfilerを起動し、 プロファイリングされたJVMをJProfilerメインウィンドウに接続することができます。
すべてのIDE統合は、JProfilerインストールのintegrations
ディレクトリに含まれています。原則として、そのディレクトリ内のアーカイブは、
各IDEのプラグインインストールメカニズムを使用して手動でインストールできます。しかし、IDE統合をインストールする推奨方法は、
メインメニューからSession→IDE integrationsを呼び出すことです。
IDEからのプロファイリングセッションは、JProfilerに独自のセッションエントリを取得しません。なぜなら、そのようなセッションはJProfiler GUIから開始できないからです。 プロファイリング設定は、IDEの設定に応じて、プロジェクトごとまたは実行構成ごとに永続化されます。
IDEに接続されているとき、JProfilerはツールバーにウィンドウスイッチャーを表示し、IDEの関連ウィンドウに簡単にジャンプできるようにします。 すべてのShow Sourceアクションは、JProfilerの組み込みソースビューアの代わりにIDEで直接ソースを表示します。
IDE統合については、後の章で詳しく説明されています。
アタッチモード
JVMをプロファイリングするつもりであることを事前に決定する必要はありません。JProfilerのアタッチ機能を使用すると、実行中のJVMを選択し、 プロファイリングエージェントをその場でロードできます。 アタッチモードは便利ですが、いくつかの欠点があることを知っておくべきです:
- プロファイリングしたいJVMを実行中のJVMのリストから特定する必要があります。これは、同じマシンで多くのJVMが実行されている場合には難しいことがあります。
- 多くのクラスを再定義してインストルメンテーションを追加する必要があるため、追加のオーバーヘッドがあります。
- JProfilerの一部の機能はアタッチモードでは利用できません。これは主に、JVMTIの一部の機能はJVMが初期化されるときにのみオンにでき、 JVMのライフサイクルの後の段階では利用できないためです。
- 一部の機能は、すべてのクラスの大部分にインストルメンテーションが必要です。クラスがロードされている間にインストルメンテーションを追加するのは安価ですが、 クラスがすでにロードされているときにインストルメンテーションを追加するのはそうではありません。そのような機能は、アタッチモードを使用する場合はデフォルトで無効になっています。
-
アタッチ機能は、OpenJDK JVM、バージョン6以上のOracle JVM、最近のOpenJ9 JVM(8u281+、11.0.11+またはJava 17+)またはそのようなリリースに基づくIBM
JVMでサポートされています。
JVMには
-XX:+PerfDisableSharedMem
および-XX:+DisableAttachMechanism
のVMパラメータを指定してはいけません。
JProfilerのスタートセンターのQuick Attachタブには、プロファイリング可能なすべてのJVMがリストされます。リストエントリの背景色は、 プロファイリングエージェントがすでにロードされているか、JProfiler GUIが現在接続されているか、オフラインプロファイリングが設定されているかを示します。
プロファイリングセッションを開始すると、セッション設定ダイアログでプロファイリング設定を構成できます。同じプロセスを繰り返しプロファイリングする場合、 同じ設定を何度も再入力したくないので、クイックアタッチ機能で作成されたセッションを閉じるときに永続的なセッションを保存できます。 次回このプロセスをプロファイリングしたい場合は、Quick Attachタブの代わりにOpen Sessionタブから保存されたセッションを開始します。 実行中のJVMを選択する必要がありますが、プロファイリング設定は以前に構成したものと同じです。
ローカルサービスへのアタッチ
JVMのアタッチAPIは、呼び出しプロセスがアタッチしたいプロセスと同じユーザーとして実行されることを要求するため、 JProfilerによって表示されるJVMのリストは現在のユーザーに限定されます。異なるユーザーによって起動されたプロセスは主にサービスです。 サービスにアタッチする方法は、Windows、Linux、およびUnixベースのプラットフォームで異なります。
Windowsでは、アタッチダイアログにShow Servicesボタンがあり、ローカルで実行中のすべてのサービスがリストされます。 JProfilerは、どのユーザーで実行されているかに関係なく、それらのプロセスにアタッチできるようにブリッジ実行ファイルを起動します。
Linuxでは、JProfilerはPolicyKitを通じてUIでユーザーを直接切り替えることをサポートしており、これはほとんどのLinuxディストリビューションに含まれています。 アタッチダイアログでSwitch userをクリックすると、別のユーザー名を入力し、システムパスワードダイアログで認証できます。
macOSを含むUnixベースのプラットフォームでは、または su
を使用して異なるユーザーとして
コマンドラインツール sudo
を実行できます。UnixバリアントやLinuxディストリビューションに応じて、
macOSやUbuntuのようなDebianベースのLinuxディストリビューションでは jpenable
が使用されます。
sudo
sudoを使用する場合、次のように呼び出します:
sudo -u userName jpenable
su userName -c jpenable
はJVMを選択し、プロファイリングエージェントがリッスンしているポートを教えてくれます。その後、
JProfiler UIからのローカルセッションまたはjpenableによって指定されたポートに直接接続するSSH接続で接続できます。
jpenable
リモートマシン上のJVMへのアタッチ
プロファイリングの最も要求の厳しいセットアップはリモートプロファイリングです。JProfiler GUIはローカルマシンで実行され、 プロファイリングされるJVMは別のマシンで実行されます。プロファイリングされるJVMに-agentpath VMパラメータを渡すセットアップでは、 リモートマシンにJProfilerをインストールし、ローカルマシンでリモートセッションを設定する必要があります。 JProfilerのリモートアタッチ機能を使用すると、そのような変更は必要ありません。リモートマシンにログインするためのSSH資格情報が必要なだけです。
SSH接続により、JProfilerはInstalling JProfiler
ヘルプトピックで説明したエージェントパッケージをアップロードし、
リモートマシンで含まれているコマンドラインツールを実行できます。ローカルマシンでSSHを設定する必要はありません。JProfilerには独自の実装が付属しています。
最も簡単なセットアップでは、ホスト、ユーザー名、および認証を定義するだけです。
SSH接続を使用すると、JProfilerは実行中のJVMを自動的に検出するか、プロファイリングエージェントがすでにリッスンしている特定のポートに接続できます。
後者の場合、リモートマシンでまたは jpenable
を使用し、
プロファイリング用の特別なJVMを準備します。その後、SSHリモートアタッチを設定して、設定されたプロファイリングポートに直接接続できます。
jpintegrate
自動検出は、SSHログインユーザーとして開始されたリモートマシン上のすべてのJVMをリストします。ほとんどの場合、
これはプロファイリングしたいサービスを開始したユーザーではありません。サービスを開始するユーザーは通常SSH接続を許可されていないため、
JProfilerはSwitch Userハイパーリンクを追加し、または sudo
を使用してそのユーザーに切り替えることができます。
su
複雑なネットワークトポロジーでは、リモートマシンに直接接続できないことがあります。その場合、GUIでマルチホップSSHトンネルを使用してJProfilerに接続するように指示できます。 SSHトンネルの終点では、通常「127.0.0.1」に直接ネットワーク接続を行うことができます。
他の認証メカニズムについては、OpenSSHトンネルモードを使用できます。OpenSSH実行ファイルを使用する場合、コマンドラインで入力するようにホスト名を入力します。 これもOpenSSH設定ファイルで設定されたエイリアスである可能性があります。ホスト名のほかに、ポートとユーザー名をオプションで指定できます。 Windowsでは、Microsoftによる組み込みのOpenSSHクライアントのみがサポートされています。
SSHオプションテキストフィールドは、OpenSSH実行ファイルに指定する追加の引数を任意に受け取ります。これは、たとえばAWSセッションマネージャーを介してSSH接続をトンネルする方法についての チュートリアルで指示された手順に従う場合に特に便利です。
HPROFスナップショットは、SSHログインユーザーとして開始されたJVMに対してのみ取得できます。これは、HPROFスナップショットがJVMを開始したユーザーのアクセス権で 書き込まれる中間ファイルを必要とするためです。セキュリティ上の理由から、ダウンロードのためにSSHログインユーザーにファイル権限を移譲することはできません。 フルプロファイリングセッションにはそのような制限はありません。
Dockerコンテナで実行されているJVMへのアタッチ
Dockerコンテナには通常SSHサーバーがインストールされておらず、Dockerコンテナでを使用することはできますが、
Dockerファイルで指定しない限り、プロファイリングポートは外部からアクセスできません。
jpenable
JProfilerでは、WindowsまたはmacOSのローカルDocker Desktopインストールで実行されているJVMにアタッチすることができ、
クイックアタッチダイアログでDockerコンテナを選択します。デフォルトでは、JProfilerは実行ファイルへのパスを自動的に検出します。
代わりに、一般設定ダイアログの「外部ツール」タブで設定することもできます。
docker
コンテナを選択すると、Dockerコンテナ内で実行されているすべてのJVMが表示されます。JVMを選択すると、JProfilerはDockerコマンドを使用して、 選択したコンテナにプロファイリングエージェントを自動的にインストールし、JVMをプロファイリング用に準備し、プロファイリングプロトコルを外部にトンネルします。
リモートDockerインストールの場合、SSHリモートアタッチ機能を使用し、リモートマシン上のDockerコンテナを選択できます。ログインユーザーがdockerグループに属していない場合は、 上記のようにユーザーを切り替えることができます。
リモートアタッチダイアログのSelect containerハイパーリンクを使用して、実行中のDockerコンテナを選択し、その中で実行されているすべてのJVMを表示できます。
Kubernetesクラスターで実行されているJVMへのアタッチ
Kubernetesクラスターで実行されているJVMをプロファイリングするには、JProfilerはコマンドラインツールを使用して、
ポッドとコンテナを発見し、コンテナに接続してそのJVMをリストし、最終的に選択したJVMに接続します。
kubectl
コマンドラインツールは、ローカルコンピュータまたはSSHアクセスを持つリモートマシンで利用可能である可能性があります。
JProfilerは両方のシナリオを直接サポートしています。ローカルインストールの場合、JProfilerは kubectl
へのパスを自動的に検出しようとしますが、
一般設定ダイアログの「外部ツール」タブで明示的なパスを設定することもできます。
kubectl
JProfilerは、検出されたコンテナを3レベルのツリーでリストします。トップにはネームスペースノードがあり、検出されたポッドを含む子ノードがあります。 リーフノードはコンテナ自体であり、実行中のJVMの選択に進むために1つを選択する必要があります。
は、Kubernetesクラスターに接続するための認証に追加のコマンドラインオプションを必要とする場合があります。
これらのオプションは、コンテナ選択ダイアログの上部に入力できます。これらのオプションは機密情報である可能性があるため、
再起動時にそれらを記憶するチェックボックスを明示的に選択した場合にのみディスクに保存されます。このチェックボックスをオフにすると、
以前に保存された情報が直ちにクリアされます。
kubectl
実行中のJVMの表示名の設定
JVM選択テーブルでは、表示されるプロセス名は、プロファイリングされたJVMのメインクラスとその引数です。exe4jまたはinstall4jによって生成されたランチャーの場合、 実行ファイル名が表示されます。
たとえば、同じメインクラスを持つ複数のプロセスがあり、それらを区別できない場合に、表示名を自分で設定したい場合は、
VMパラメータ-Djprofiler.displayName=[name]
を設定できます。名前にスペースが含まれている場合は、シングルクォートを使用します:
-Djprofiler.displayName='My name with spaces'
必要に応じて、ダブルクォートでVMパラメータ全体を引用します。
-Djprofiler.displayName
に加えて、JProfilerは-Dvisualvm.display.name
も認識します。