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はサポートされていません。
ローカルで起動されたセッションは、メインメニューからセッション→変換ウィザードを呼び出すことで変換ウィザードによってスタンドアロンセッションに変換できます。アプリケーションセッションをリモートに変換は単に開始スクリプトを作成し、-agentpath
VMパラメータをJava呼び出しに挿入します。アプリケーションセッションをオフラインに変換は、オフラインプロファイリングのための開始スクリプトを作成します。これは、設定が起動時にロードされ、JProfiler
GUIが必要ないことを意味します。アプリケーションセッションを再配布セッションに変換は同じことを行いますが、プロファイリングエージェントと設定ファイルを含むディレクトリjprofiler_redist
をその隣に作成し、JProfilerがインストールされていない別のマシンにそれを送ることができます。
プロファイルされたアプリケーションを自分で開発する場合は、起動されたセッションの代わりにIDE統合を使用することを検討してください。それはより便利で、より良いソースコードナビゲーションを提供します。アプリケーションを自分で開発していないが、既に開始スクリプトを持っている場合は、リモート統合ウィザードを使用することを検討してください。それはJava呼び出しに追加する必要がある正確なVMパラメータを教えてくれます。
統合ウィザード
JProfilerの統合ウィザードは、スタートスクリプトや設定ファイルをプログラム的に変更して追加のVMパラメータを含めることができる多くの有名なサードパーティコンテナを扱います。いくつかの製品では、VMパラメータが引数として渡されるか、環境変数を介して渡されるスタートスクリプトを生成できます。
すべてのケースで、サードパーティ製品から特定のファイルを見つける必要があります。これにより、JProfilerは必要なコンテキストを持って変更を行うことができます。いくつかの一般的なウィザードは、プロファイリングを有効にするために何をする必要があるかについての指示を与えるだけです。
各統合ウィザードの最初のステップは、ローカルマシンでプロファイルするか、リモートマシンでプロファイルするかの選択です。ローカルマシンの場合、JProfilerは既にプラットフォームを知っており、JProfilerがインストールされている場所と設定ファイルがどこにあるかを知っているため、提供する情報は少なくて済みます。
重要な決定は、上記で議論された「起動モード」です。デフォルトでは、プロファイリング設定は起動時にJProfiler UIから送信されますが、JVMをすぐに起動させるようにプロファイリングエージェントに指示することもできます。後者の場合、プロファイリング設定はJProfiler GUIが接続したときに適用できます。
しかし、プロファイリング設定を含む設定ファイルを指定することもできます。これははるかに効率的です。これは設定の同期ステップで行われます。この場合の主な問題は、プロファイリング設定をローカルで編集するたびに設定ファイルをリモート側と同期する必要があることです。最もエレガントな方法は、リモートアドレスステップでSSHを介してリモートマシンに接続し、設定ファイルをSSHを介して自動的に転送できるようにすることです。
統合ウィザードの最後に、プロファイリングを開始するセッションが作成され、非一般的なケースでは、アプリケーションサーバーなどのサードパーティ製品も起動されます。
外部スタートスクリプトは、セッション設定ダイアログのアプリケーション設定タブでスタートスクリプトを実行およびストップスクリプトを実行オプションによって処理され、URLでブラウザを開くチェックボックスを選択することでURLを表示できます。ここは、リモートマシンのアドレスと設定同期オプションを変更できる場所でもあります。
統合ウィザードはすべて、プロファイルされたJVMがリモートマシンで実行されているケースを処理します。しかし、設定ファイルやスタートスクリプトを変更する必要がある場合は、それをローカルマシンにコピーし、変更されたバージョンをリモートマシンに戻す必要があります。コマンドラインツールをリモートマシンで直接実行し、その場で変更を行う方が便利かもしれません。 jpintegrate
はJProfilerの完全なインストールを必要とし、JProfiler
GUIと同じJRE要件があります。
jpintegrate
リモートプロファイリングセッションを開始する際にエラーが発生した場合は、トラブルシューティングガイドを参照して、問題を解決するために取ることができるステップのチェックリストを確認してください。
IDE統合
アプリケーションをプロファイルする最も便利な方法は、IDE統合を通じて行うことです。開発中に通常IDEからアプリケーションを起動する場合、IDEはすでに必要な情報をすべて持っており、JProfilerプラグインは単にプロファイリング用のVMパラメータを追加し、必要に応じてJProfilerを起動し、プロファイルされたJVMをJProfilerメインウィンドウに接続することができます。
すべてのIDE統合は、JProfilerインストールのintegrations
ディレクトリに含まれています。原則として、そのディレクトリ内のアーカイブは、各IDEのプラグインインストールメカニズムを使用して手動でインストールできます。しかし、IDE統合をインストールするための推奨方法は、メインメニューからセッション→IDE統合を呼び出すことです。
IDEからのプロファイリングセッションは、JProfilerで独自のセッションエントリを取得しません。なぜなら、そのようなセッションはJProfiler GUIから開始できないからです。プロファイリング設定は、IDEの設定に応じて、プロジェクトごとまたは実行構成ごとに永続化されます。
IDEに接続されているとき、JProfilerはツールバーにウィンドウスイッチャーを表示し、関連するウィンドウに簡単に戻ることができます。すべてのソースを表示アクションは、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のスタートセンターのクイックアタッチタブには、プロファイル可能なすべてのJVMがリストされています。リストエントリの背景色は、プロファイリングエージェントがすでにロードされているか、JProfiler GUIが現在接続されているか、オフラインプロファイリングが設定されているかを示します。
プロファイリングセッションを開始するとき、セッション設定ダイアログでプロファイリング設定を構成できます。同じプロセスを繰り返しプロファイルする場合、同じ設定を何度も再入力したくないので、クイックアタッチ機能で作成されたセッションを閉じるときに永続的なセッションを保存できます。次回このプロセスをプロファイルしたいときは、クイックアタッチタブではなくセッションを開くタブから保存されたセッションを開始します。実行中のJVMを選択する必要がありますが、プロファイリング設定は以前に構成したものと同じです。
ローカルサービスへのアタッチ
JVMのアタッチAPIは、呼び出しプロセスがアタッチしたいプロセスと同じユーザーとして実行されることを要求するため、JProfilerによって表示されるJVMのリストは現在のユーザーに限定されます。異なるユーザーによって起動されたプロセスは主にサービスです。サービスにアタッチする方法は、Windows、Linux、およびUnixベースのプラットフォームで異なります。
Windowsでは、アタッチダイアログにサービスを表示ボタンがあり、すべてのローカルで実行中のサービスがリストされます。JProfilerは、どのユーザーで実行されていても、それらのプロセスにアタッチできるようにブリッジ実行ファイルを起動します。
Linuxでは、JProfilerはPolicyKitを通じてUIで直接ユーザーを切り替えることをサポートしています。これはほとんどのLinuxディストリビューションの一部です。アタッチダイアログでユーザーを切り替えるをクリックすると、別のユーザー名を入力し、システムパスワードダイアログで認証できます。
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は-agentpath
VMパラメータをプロファイルされたJVMに渡すセットアップでは、リモートマシンにJProfilerをインストールし、ローカルマシンでリモートセッションを設定する必要があります。JProfilerのリモートアタッチ機能では、そのような変更は必要ありません。リモートマシンにログインするためのSSH資格情報が必要なだけです。
SSH接続により、JProfilerは-agentpath
VMパラメータをプロファイルされたJVMに渡すセットアップでは、リモートマシンにJProfilerをインストールし、ローカルマシンでリモートセッションを設定する必要があります。JProfilerのリモートアタッチ機能では、そのような変更は必要ありません。リモートマシンにログインするためのSSH資格情報が必要なだけです。
自動検出は、SSHログインユーザーとして開始されたリモートマシン上のすべてのJVMをリストします。ほとんどの場合、これはプロファイルしたいサービスを開始したユーザーではありません。サービスを開始するユーザーは通常SSH接続を許可されていないため、JProfilerはユーザーを切り替えるハイパーリンクを追加し、または sudo
を使用してそのユーザーに切り替えることができます。
su
複雑なネットワークトポロジーでは、リモートマシンに直接接続できないことがあります。その場合、JProfilerにGUIでマルチホップSSHトンネルで接続するように指示できます。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コンテナでjpenableを使用することはできますが、Dockerファイルで指定しない限り、プロファイリングポートは外部からアクセスできません。
JProfilerでは、WindowsまたはmacOSのローカルDocker
Desktopインストールで実行されているJVMにアタッチすることができ、クイックアタッチダイアログでDockerコンテナを選択します。デフォルトでは、JProfilerは実行ファイルへのパスを自動的に検出します。あるいは、一般設定ダイアログの「外部ツール」タブでそれを設定できます。
docker
コンテナを選択すると、Dockerコンテナ内で実行されているすべてのJVMが表示されます。JVMを選択すると、JProfilerはDockerコマンドを使用して選択したコンテナにプロファイリングエージェントを自動的にインストールし、プロファイリングの準備をし、プロファイリングプロトコルを外部にトンネルします。
リモートDockerインストールの場合、SSHリモートアタッチ機能を使用してリモートマシン上のDockerコンテナを選択できます。ログインユーザーがdockerグループに属していない場合は、上記のようにユーザーを切り替えることができます。
リモートアタッチダイアログのコンテナを選択ハイパーリンクを使用して、実行中の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
も認識します。