2015-07-02 4 views
3

Я пытаюсь получить доступ к классам из servlet-api в javaagent jar, который добавлен в мое приложение через флаг -javaagent: my-agent.jar. Мое приложение работает на Tomcat. Проблема в том, что я получаю исключение ClassNotFoundException, потому что контейнер агента загружается загрузчиком классов, который не имеет доступа к классам servlet-api.Доступ к сервлет-api в javaagent

Более конкретно, я хочу, чтобы включить ServletContainerInitializer в моем javaagent

public class MyInitializer implements ServletContainerInitializer { 
    @Override 
    public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException { 
     System.out.println(ctx); 
    } 
} 

META-INF/услуги/javax.servlet.ServletContainerInitializer

org.example.MyInitializer 

В результате ClassNotFoundException потому ServletContainerInitializer не мог быть найденным.

Есть ли способ получить доступ к сервлета-api внутри javaagent? Или, в более общем плане, можно ли получить доступ к любому классу, который загружается через ApplicationClassLoader, например классы из Spring Framework?

+0

Вы решили что? – nadavy

+1

нет, еще нет :-( – Felix

+0

@Felix Любые удачи при загрузке динамического сервлета из javaagent jar? – Vikdor

ответ

1

Если ваш агент имеет premain метод с подписью как

public static void premain(String agentArgs, Instrumentation inst) 

Вы получаете руки на Instrumentation объект, который предоставляет методы getAllLoadedClasses() и getInitiatedClasses(ClassLoader). Теперь было бы неудобно искать эти массивы каждый раз и использовать экземпляры Class через Reflection. Но вы можете использовать эти методы, чтобы найти нужный класс API, определить его время выполнения ClassLoader и создать новый ClassLoader, используя его в качестве родителя-разрешения и указывая на ваши классы агентов, которые их требуют.

+0

Как бы это выглядело как «указывать на мои классы агентов»? Еще одна проблема заключается в том, что класс MyInitializer загружается сервером приложений при запуске, так что еще труднее запутаться с загрузчиками классов. – Felix

+1

Например, вы помещаете все классы, относящиеся к 'MyInitializer', в файл jar и создаете' URLClassLoader', используя URL-адрес 'file:', указывающий на файл jar Вероятно, ваш агент должен отложить инициализацию до тех пор, пока контейнер сервлета не будет полностью инициализирован. Я не знаю достаточно о вашем случае использования, чтобы сообщить вам, какое условие ждать. Но обратите внимание, что вы можете использовать 'addTransformer' для регистрации трансформатора который просто возвращает 'null', чтобы не делать никакого фактического преобразования. Поскольку этот трансформатор будет вызываться для каждого загруженного класса, вы узнаете, когда ваш желаемый класс получит s загружен tomcat. – Holger

0

Что сработало для меня, я добавил файл servlet-api.jar в ClassPool.insertClassPath. И это решило проблему.

ClassPool $pool = ClassPool.getDefault(); 
      try { 
       $pool.insertClassPath("/apache-tomcat-7.0.50/lib/servlet-api.jar"); 
      } catch (NotFoundException e) { 
       throw new RuntimeException(e); 
      } 
    return $pool; 

https://github.com/presci/MyAgent.git

 Смежные вопросы

  • Нет связанных вопросов^_^