2016-03-22 8 views
2

Я использую экземпляр tomcat7 для запуска приложения Java. Моему приложению требуется инструментарий Java. Это делается с помощью javaagent, и я передаю агент при запуске в JVM в скрипте setenv.bat.Не удается открыть Java Instrumentation для tomcat jvm

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

В файле манифеста у меня есть необходимый раздел:

Premain-Class: package.name.agent.ExposeInstrumentation 

В методе premain класса агента присвоить приборы, предоставленные 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 получает инструментарий, но когда я называю getInstrumentation позже в моем коде s_instumentation установлено нулевое значение. Это странно, потому что ценность остается актуальной, думая о жизни программы.

+0

Действительно ли ваш метод 'premain' называется? – Berger

+0

premain выполняется, но я не получаю никаких инструментов – dragosb

ответ

1

Я предполагаю, что вы грузите класс ExposeInstrumentation дважды. Один раз загрузчик класса приложения, который равен child-first (reverse-order), и один раз через Java-агент, где класс автоматически загружается загрузчиком системного класса. В результате класс ExposeInstrumentation загружается дважды, когда вы получаете доступ к тому из своего приложения, где это поле не задано.

Вы можете решить эту проблему путем явного доступа к классу, нагруженный системный класс загрузчик:

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, чтобы он не загружался дважды? – dragosb

+0

Должен был 'loadClass' вместо' findClass'. Вы можете предотвратить дублируемую загрузку, поместив класс ExposeInstrumentation в собственный модуль и объявив ему видимую видимость видимости для веб-приложения. Пока агент подключен, это будет работать. –