問題タブ [jvmti]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - Attach API に java_pid ファイルがないため、AttachNotSupportedException が発生する
独自のプロファイラーを構築し、JVMTI API を使用してネイティブ ライブラリ エージェントを構築します。このエージェントは、追加パラメーター -agentlib を使用して、JVM と一緒に開始できます。さらに、実行中の JVM にエージェントを挿入できるAttach API があります。次のコードを使用して、この機能をプロファイラーに実装したいと考えました。
それは何をするためのものか?利用可能な実行中のすべての仮想マシン ( VirtualMachine.list()
) から最初の仮想マシンを選択し、それにアタッチしてエージェントをロードしようとします。libagent.so という名前の UNIX システム上のエージェントは見つかりますが、エージェントをロードしようとすると、次の例外がスローされます。
ソース コードを調べると、という名前のファイルが見つからないため、この例外がスローされます.java_pid<pid>
。ドキュメントには、この種のファイルに関する多くの情報が見つかりませんでした。この種のファイルはもう使われていないとよく耳にしますが、私は Java 1.6 を実行しています。
また、他の JVM にアタッチしようとしました。実際、このアタッチ プロセスを動的に保ちました。テスト上の理由から、任意の JVM にアタッチしようとしました。
これは、 sun.tools.attach: LinuxVirtualMachine.javaから取られた、例外につながるコードです:
それは、ルートから/proc/<pid>
ディレクトリを探していると言います。JDK7 の変更セットを見ると、コードJDK7 Changeset to LinuxVirtualMachine に変更を加えているようです。
java - プロファイリング中の notifyAll() 呼び出しの数の違い
wait()
とで呼び出しを表示するために、JVMTI を使用して単純なプロファイラーを実装しましたnotifyAll()
。テストケースとして、私はを使用しています。Oracle の生産者消費者の例。次の 3 つのイベントがあります。
- notifyAll() が呼び出されます
- wait() が呼び出される
- wait() が残っている
wait()
イベントMonitorEnter
とMonitorExit
. _ 名前を持つメソッドが終了すると、notifyAll()
呼び出しがプロファイリングされますnotifyAll
。
これで、次の結果が得られました。1 つ目はプロファイラー自体からのもので、2 つ目は適切なステートメントを配置したJava からのものです。System.out.println
この不一致の原因について誰かが説明していますか? notifyAll()
何度も呼ばれます。これは、Java の要求からオペレーティング システムへの誤検知応答が原因である可能性があると言われました。
オペレーティング システムに送信されたnotifyAll()
要求と、要求が成功したように見える偽陽性の応答が送信されます。notifyAll
代わりにプロファイリング メソッド呼び出しによってログに記録されるためMonitorEnter
、これが待機で発生しない理由を説明できます。
言い忘れましたが、プログラムを個別に実行したわけではありません。両方のログは同じ実行からのものです。
追加情報
元は回答として追加されていましたが、extraneon によって質問に移動されました。
追加の notifyAll の一部がどこから来ているかがわかったと思います。notifyAll が呼び出されるメソッド コンテキストのプロファイリングを追加しました。
しかし、これらの外部呼び出しがなくても、printf デバッグに表示されない notifyAll 呼び出しがたくさんあります。
java - JVMTIを使用してJavaの実行時間を測定する
JVMTIを使用して実装するプロファイラーについて、すべてのJavaメソッドの実行時間の測定を開始したいと思います。JVMTIは次のイベントを提供します。
MethodEntry
MethodExit
したがって、これは実装が非常に簡単ですが、APIでこのメモに出くわしました。
メソッドの開始イベントまたは終了イベントを有効にすると、多くのプラットフォームでパフォーマンスが大幅に低下するため、パフォーマンスが重要な使用法(プロファイリングなど)についてはお勧めしません。このような場合は、バイトコードインストルメンテーションを使用する必要があります。
しかし、私のプロファイリングエージェントはヘッドレスで動作します。つまり、収集されたデータはシリアル化され、ソケットを介してサーバーアプリケーションに送信され、結果が表示されます。バイトコードインストルメンテーションを使用してこれをどのように実現する必要がありますか。ここから先に進む方法が少し混乱しています。戦略を切り替える必要がある場合、またはこの問題にどのように取り組むことができるか、誰かが私に説明してもらえますか?
java - 実行時にJVMTIエージェントをアンロードしますか?
実行時にJVMTIエージェントをロードするためにアタッチAPIを使用しています。エージェントがロードされているJVMを終了せずにプログラムが完了したら、JVMTIエージェントをアンロードしたいと思います。このドキュメントによると、アタッチAPIからこれを行う方法はありません。Java APIを介して、またはJVMTIエージェント内からエージェントに自身をアンロードさせる他の方法はありますか?
java - JVMTI を使用して GC によって解放されたメモリ量を取得する
JVMTI を使用して、GC によって解放されたメモリの量を把握しようとしています。これは、プロファイラーの一部として使用されます。
JVMTI を使用して、GC_START および GC_END のイベントを取得できます。JVMTI は、ヒープをウォークスルーする機能も提供しており、そこから正確な現在のサイズを取得できます。論理的には、GC_START と GC_END でヒープ サイズを取得してから、ヒープ サイズの差を取得できます。
問題は、GC_START および GC_END イベント ハンドラーが機能している間、ほとんどの JVMTI 機能が無効になり、JVMTI_ERROR_UNATTACHED_THREAD (115) エラーが発生することです。
JVMTI APIリファレンス http://download.oracle.com/javase/6/docs/platform/jvmti/jvmti.html#GarbageCollectionStartを見ると
「ガベージ コレクションの開始 このイベントは、VM がまだ停止している間に送信されます。したがって、イベント ハンドラは、JNI 関数を使用してはならず、JVM TI 関数を使用してはなりません。ただし、そのような使用を明確に許可するものを除きます (raw モニタ、メモリ管理、および環境ローカルを参照してください)。ストレージ機能)」</p>
そのため、イベント ハンドラからメモリにアクセスできないようです。
エラーは、GetCurrentHeapMemory 関数でスローされます。
コードは次のとおりです /* * memory_collector.c * * 作成日: 2011 年 5 月 8 日 * 作成者: ycarel */
JVMTI を使用してこの情報を収集する方法に関する情報を入手できれば幸いです。JVMTI の代替手段も歓迎します。
ありがとう
java - JVMTI によるデッドロック検出
JavaでJVMTIを使ってデッドロックを動的に検出できるかどうか疑問に思っています。同期ステートメントを使用したモニターでのアクションを示す 2 つのイベントがあります。
モニター競合エンター
スレッドが、別のスレッドによってすでに取得されている Java プログラミング言語モニターに入ろうとしたときに送信されます。
モニターの競合が入力されました
別のスレッドによって解放されるのを待った後、スレッドが Java プログラミング言語モニターに入ったときに送信されます。
つまり、JVMTI では、すでにロックされているモニターしか見ることができません。待機グラフを再構築したかったのですが、どのスレッドにも保持されていないロックが取得されたことを示すイベントがありませんでした。不可能だよ。
代替手段はありますか?Unix の SIGQUIT コマンドは、デッドロックを表示するスレッド ダンプを許可しますが、これは JVMTI 内では不可能のようです。
java - JVMTI によるメソッド実行の測定
MethodEntry
JVMTI が提供するおよびイベント フックを使用してMethodExit
、Java で実行されたメソッドの時間をどのように測定しますか?
簡単に言うと、次のとおりです。time2 - time1
しかし、私が見る問題は、さまざまな方法をどのように区別するのですか? methodID はありますが、再帰呼び出しはどうでしょうか。メソッドを開いた後、メソッドを閉じるのはいつですか?
スタック トレースを比較する必要がありますか? 入力されたメソッドを追跡するための意味のあるデータ構造は何でしょうか? 何かのようなものMap<StackTrace,Time>?
java - プロファイリングとインストルメンテーション-Java
基本的な質問:JVMは、JVMのプロファイリングとデバッグのためのネイティブAPIであるJVMTIを提供します。JVMインストルメンテーションも同じことを行います(それは正しいですか?)。はいの場合、両方の違いは何ですか?
windows - エラーなしでエージェントをコンパイルし、「無効な Windows イメージ」というメッセージを表示する
1 週間以来、私は JVMTI デモ セットのデモ バージョンをコンパイルしようとしています。この場合、HeapViewer のソース コードをコンパイルしようとしました (HeapViewer.c ファイルの名前を HeapViewerByMG に変更しました)。別のコンパイラを試し、stackOverflow で見つけた次のコードを主に使用しました。
コードはどちらの場合も正常にコンパイルされますが、dll ファイルを使用しようとすると、次のエラーが発生します。
「アプリケーションまたは DLL (...)\heapViewerByMG.dll は有効な Windows イメージではありません。これをインストール ディスクと照合してください。」
このメッセージの意味も調べました。調査によると、これは破損したファイルですが、JVM によって特定のソース コードをコンパイルしたため、これを除外できます。とにかく、ファイルを正常に実行させるために必要なのは、別のオプションコマンドだと思います。あなたの誰かがアイデアを持っていますか?
私のシステムの詳細は次のとおりです。
または、Microsoft Compiler を 64 ビットから 32 ビットに変更した後 (エージェントを起動したときの古いエラー メッセージの 1 つだったため)
そして、2.00 GB の RAM を搭載した Intel(R) 4 CPU 2.80 GHz で Microsoft Windows XP Professional バージョン 2002 Service Pack 3 を実行しています。
あのシステムでごめんなさい。通常、私は MacBook Pro 2010 (2.8GHz Intel Core i7) を使用していますが、MacOS には JVMTI デモ版のサポートが含まれていないことがわかりました :(
誰かが私を助けてくれることを願っています。
こんにちは、マーカス G.
java - JVMTI を使用したスレッド対応のヒープ割り当ての追跡
プロファイリングの作成 ヒープ プロファイリングの典型的なタスクも実装します。具体的には、どのスレッドがどのくらいのデータを割り当てたかを追跡したいと思います。JVMTI を使用して、イベントVM Object AllocationおよびObject Freeにフックするだけで十分だと思いました。悲しいことに、への呼び出しが原因で最初のイベントがトリガーされないことを読みましたnew
。
私が最後に考えたのは、イベントMethodExitの名前が<init>
であるかどうかをチェックし、この呼び出しをオブジェクト割り当てとして宣言することでした。ただし、このイベント内ではオブジェクトを取得できないため、呼び出すことができませんGetObjectSize
。
ヒープを単純に反復するだけでは、どのオブジェクトがどのスレッドによって割り当てられたかに関する情報はありません。これを実装する方法を知っている人はいますか?