Проверьте, загружен ли aspectjweaver (или любой javaagent)
Есть ли (предварительно переносимый) способ проверить, была ли JVM заявлена с определенным -javaagent
?
В частности, мне интересно узнать, загружен ли трейлер времени загрузки aspectj. (Я пытаюсь предоставить полезную ошибку MSG в случае неправильного запуска).
2 ответа
Следующий код показывает
- способ определить любой
-javaagent:...
Аргументы JVM, - способ проверить, существует ли класс точки входа ткацкого агента AspectJ (тот, который указан в записи манифеста)
Premain-Class:
of aspectjweaver.jar) загружен.
Первый просто доказывает, что аргумент был задан в командной строке, а не то, что агент был фактически найден и запущен.
Последнее просто доказывает, что ткач доступен на пути к классам, а не то, что он фактически был запущен в качестве агента. Сочетание обоих должно дать вам большую уверенность в том, что агент действительно активен.
package de.scrum_master.app;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.List;
public class Application {
public static void main(String[] args) {
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
List<String> arguments = runtimeMxBean.getInputArguments();
for (String argument : arguments) {
if (argument.startsWith("-javaagent:"))
System.out.println(argument);
}
try {
Class.forName("org.aspectj.weaver.loadtime.Agent");
} catch (ClassNotFoundException e) {
System.err.println("WARNING: AspectJ weaving agent not loaded");
}
}
}
Вам также может пригодиться вопрос " Запуск агента Java после запуска программы" и некоторые ответы на него.
Обновить:
Хорошо, вот комбинация моего и вашего собственного решения, но оно действительно работает, даже если ткач не доступен, что важно, потому что это то, что вы хотите проверить в первую очередь:
public static boolean isAspectJAgentLoaded() {
try {
Class<?> agentClass = Class.forName("org.aspectj.weaver.loadtime.Agent");
Method method = agentClass.getMethod("getInstrumentation");
method.invoke(null);
} catch (Exception e) {
//System.out.println(e);
return false;
}
return true;
}
Обновление 2:
После некоторого обсуждения с OP Bacar я решил предложить решение, которое не использует отражение, но ловит NoClassDefError
вместо:
public static boolean isAspectJAgentLoaded() {
try {
org.aspectj.weaver.loadtime.Agent.getInstrumentation();
} catch (NoClassDefFoundError | UnsupportedOperationException e) {
System.out.println(e);
return false;
}
return true;
}
Теперь оба основных типа ошибок
- на пути к классам доступен ткацкий агент, но инструментарий не был инициирован, потому что aspectjweaver.jar не был запущен как агент Java,
- agent aspectjweaver.jar не находится на пути к классам вообще, а class
org.aspectj.weaver.loadtime.Agent
таким образом недоступен
обрабатываются изящно, возвращаясь false
после предупреждающих сообщений (в этих простых примерах только исключения, в которых четко сказано, что не так) были напечатаны на консоли.
Возможные выходы консоли для двух случаев:
java.lang.UnsupportedOperationException: Java 5 was not started with preMain -javaagent for AspectJ
java.lang.NoClassDefFoundError: org/aspectj/weaver/loadtime/Agent
Я обнаружил следующие работы (проверено на 1.8.4), хотя он использует недокументированные функции aspectjweaver, поэтому может не работать в разных версиях.
public static boolean isAspectJAgentLoaded() {
try {
org.aspectj.weaver.loadtime.Agent.getInstrumentation();
return true;
} catch (UnsupportedOperationException e) {
return false;
}
}
Объяснение: когда аспект j загружается как агент, org.aspectj.weaver.loadtime.Agent.premain(...)
статический метод вызывается JVM. Это побочный эффект, который мы можем проверить. призвание getInstrumentation
либо бросает UnsupportedOperationException
(если он не был инициализирован как агент) или успешно возвращается, если это было.