2016-03-22 8 views
2

Tomcat7インスタンスを使用してJavaアプリケーションを実行しています。私のアプリケーションでは、Java計測が公開されている必要があります。これはjavaagentで行われ、起動時にエージェントをsetenv.batスクリプトのJVMに渡します。マニフェストファイルでtomcat用Java Instrumentationを公開できませんjvm

set JAVA_OPTS=%JAVA_OPTS% -javaagent:"C:\path\to\agent.jar" 

Iが必要セクションを有する:エージェントクラスのpremainメソッドで

Premain-Class: package.name.agent.ExposeInstrumentation 

を静的メソッド

を通じて静的変数にアクセス可能にJVMによって提供される機器を割り当てます
public final class ExposeInstrumentation { 
private static Instrumentation s_instrumentation; 
public static void premain(String arguments, Instrumentation instrumentation) { 
    s_instrumentation = instrumentation; 
} 

public static Instrumentation getInstrumentation() { 
    return s_instrumentation; 
} 
} 

しかし、私のコードで 私はこれを行うとき:

Instrumentation instrumentation = ExposeInstrumentation.getInstrumentation(); 

getInstrumentation()はnullを返します。

何が問題ですか?

UPDATE私はさらにいくつかのデバッグを行なったし、premainが実行されますとs_instrumentationは、計測を受けるが、私は私のコードs_instumentationの後半でgetInstrumentationを呼び出すときにnullに設定されています。これは私が価値があることを奇妙なものにしています。

+0

'premain'メソッドは実際に呼び出されていますか? – Berger

+0

premainが実行されますが、私はどんな計測器も取得しません – dragosb

答えて

1

クラスExposeInstrumentationを2回ロードしているとします。一度アプリケーションクラスローダーによってchild-first (reverse-order)であり、クラスはシステムクラスローダーによって自動的にロードされます。その結果、ExposeInstrumentationクラスは、フィールドが設定されていないアプリケーションからアクセスする場所に2回ロードされます。

あなたは明示的にシステムクラスローダによってロードされたクラスにアクセスすることによりこの問題を解決することができます

class ExposeInstrumentation { 

    // public to assure accessability 
    public static Instrumentation s_instrumentation; 

    public static void premain(String arguments, Instrumentation inst) { 
    s_instrumentation = inst; 
    } 

    public static Instrumentation getInstrumentation() { 
    try { 
     return (Instrumentation) ClassLoader.getSystemClassLoader() 
      .loadClass(ExposeInstrumentation.class.getName()) 
      .getDeclaredField("s_instrumentation") 
      .get(null); 
    } catch(Exception e) { 
     return null; 
    } 
    } 
} 

あなたはまた、エージェントのこの機能は、より(ランタイムのインストール)を提供していますByte Buddy Agent projectをチェックアウトすることができます。 Byte Buddyでは、単にByteBuddyAgent.getInstrumentation()と呼ぶことができます。

+0

...アプリケーションClassLoaderがExposeInstrumentationを読み込まないようにする方法がありますので、2回読み込まれませんか? – dragosb

+0

'findClass'の代わりに' loadClass'があったはずです。 'ExposeInstrumentation'クラスをそれ自身のモジュールに入れ、Webアプリケーションのために*提供された*スコープ依存性を宣言することで、重複ロードを防ぐことができます。エージェントが接続されている限り、これは機能します。 –

関連する問題