Javaagent是用来做什么的?

3
当我尝试查找使用Javaagent的示例时,大多数情况下都是与字节码一起使用的示例。这些示例使用第三方库,例如Javaassist。
据我所知,在Java中没有标准手段来处理字节码,在任何情况下都必须使用库。
因此,我尝试在调用defineClass()之前在自己的自定义类加载器中使用这些库。当然,它完美地工作了。我可以像使用ClassFileTransformer的transform()方法一样更改字节码。
我是否正确理解了Javaagent的另一个有用功能,而这反过来又是它们的主要特点?因为首先,javaagent会给您提供一个Instrumentation对象,而Java规范说instrument包主要用于处理字节码。但是,如果我只能实现自己的类加载器(在引入instrument包之前就可以做到的事情),那我为什么需要这样做呢?
3个回答

4

仪器化API可以在运行时使用,无需触及代码或编译的字节码。你可以对每个已编译的Java程序进行仪器化(即使没有代码)。


你能给一个例子吗? - Average Joe
非常抱歉,但是他们在文章中所做的只是使用ASM进行字节码转换。同样的操作也可以通过类加载器完成。 - Average Joe
1
好的,另一个例子:编写一个分析器,可以计算Java应用程序加载/使用的类的数量。然后使用它来对Apache Tomcat Web服务器进行分析。你如何使用自定义类加载器来实现这个目标? - isnot2bad
我不得不同意你的观点,没有办法只使用我的自定义类加载器来完成这个任务。 - Average Joe

3

我认为使用 javaagent 是不同的,因为它不是您应用程序的一部分。您可以编写例如性能分析代理,并将其与任何应用程序一起使用。


这很明智。 但据我所了解,例如Mockito使用javaagent来操作字节码。Mockito将javaagent附加到JVM上。但如果这是他们的javaagent的唯一目的,他们可以简单地使用自己的类加载器。 也许我理解有误 =) - Average Joe
我认为Mockito会在运行时动态构建代理,就像Spring AOP一样,尽管这只是我的猜测。 - Evgeniy Dorofeev

1
不要混淆Java代理和Instrumentation。Java代理可以使用Instrumentation,但不必如此。它可以使用Java平台提供的所有其他功能。不使用Instrumentation的代理的典型示例是JMX代理。查看像JVisualVM这样的工具提供的内容。它的大部分功能(除了分析器)都是通过JMX代理提供的,而不使用Instrumentation。
顺便说一下,关于您关于Instrumentation和类加载器之间区别的问题。自定义类加载器无法更改通过引导类加载器加载的类,例如java.lang.Object(尽管在执行此操作之前应三思)。此外,您的自定义类加载器必须实现原始类加载器语义才能正常工作。否则,例如,如果您尝试使用委派拦截加载,则您的类加载器将错过JVM尝试解析依赖项时加载的所有类。并且由应用程序创建的另一个ClassLoader加载的所有类(例如通过RMI)都不会由您的自定义类加载器处理。
因此,Instrumentation添加了一种独立于其ClassLoader处理类的方法,并且(可选)甚至允许在加载后根据需要更改它们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接