在没有JVM Arg的测试中加载Java代理

时间:2018-03-09 04:05:41

标签: testng javaagents

每次我从IDE运行测试时都会出现错误

java.lang.IllegalStateException: Missing the '-javaagent' JVM argument. 

如果我创建一个运行配置并添加jvm arg一切都很好。但是,下次我运行的测试不是预先配置的运行配置,我再次收到错误。

我想也许我可以使用@BeforeClass动态加载java代理。 e.g。

@BeforeClass
public void loadAgent() {
    String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();
    String pid = nameOfRunningVM.substring(0, nameOfRunningVM.indexOf('@'));
    VirtualMachine vm = VirtualMachine.attach(pid);

    Class klass = JavaAgent.class;
    CodeSource codeSource = klass.getProtectionDomain().getCodeSource();
    String agentJar = codeSource.getLocation().getPath();

    vm.loadAgent(agentJar, "");
    vm.detach();
}

(可能使用测试监听器可能意味着我不会将代码复制并粘贴到每个测试类中)

这样可行,但看起来不太合适。

有没有办法在不需要pid的情况下执行此操作?

还是有一个更好的替代方法吗?

2 个答案:

答案 0 :(得分:0)

此代码不可移植,但对于测试用例,这可能是可以接受的。没有其他方法可以将Java代理加载到已经运行的HotSpot / OpenJDK环境中。

This answer显示通过PID附加不起作用的情况的后备(因为RuntimeMXBean的实际名称模式未指定)。它归结为设置一个特殊的“魔术”系统属性并迭代所有本地JVM,查询它们的系统属性以找到你刚刚定义的那个:

String magic=UUID.randomUUID().toString()+'/'+System.nanoTime();
System.setProperty("magic", magic);
VirtualMachine vm;
for(VirtualMachineDescriptor vd:VirtualMachine.list()) try {
    vm=VirtualMachine.attach(vd);
    if(magic.equals(vm.getSystemProperties().getProperty("magic"))) break;
    vm.detach();
}

但显然,直接附加到所需的过程会更有效。

从Java 9开始,您不再需要依赖RuntimeMXBean的未指定名称模式:

VirtualMachine vm = VirtualMachine.attach(Long.toString(ProcessHandle.current().pid()));

另一方面,自我附加现在通常要求您在命令行上设置系统属性jdk.attach.allowAttachSelf,或使用像this page中讨论的更深层次的黑客。

答案 1 :(得分:0)

对于JDK8,EA Agent Loader是更好的选择,不需要pid。 但是,它已经停止使用JDK9。

我的代理人恰好称为JavaAgent的Kotlin示例!

AgentLoader.loadAgentClass(JavaAgent::class.java.name, "")