当我尝试查找使用Javaagent的示例时,在大多数情况下,它们是使用字节码的示例。这些示例使用第三方库,例如Javaassist。
据我所知,Java中没有标准的方法来处理字节码,无论如何你都不得不求助于库。
因此,在调用defineClass()
之前,我尝试在自己的自定义类加载器中使用这些库。而且,当然,它运作得非常好。我可以用相同的方式更改字节码,就像我使用ClassFileTransformer
的{{1}}方法一样。
我是否正确理解javaagents还有另一个有用的功能,反过来又是它们的主要功能?因为,首先,javaagent为您提供了一个transform()
对象,Java规范说Instrumentation
包主要用于处理字节码。但是,如果我能够实现自己的类加载器(在引入instrument
包之前我可以做的事情),为什么还需要这样做?
答案 0 :(得分:3)
可以在运行时使用Instrumentation API而无需触及代码或编译的字节代码。您可以检测每个已编译的java程序(即使没有代码)。
答案 1 :(得分:2)
我认为使用javaagent是不同的,因为它不是您的应用程序的一部分。您可以编写例如概要分析代理并将其用于任何应用程序。
答案 2 :(得分:1)
不要混淆Javaagents和Instrumentation。 Java代理可以使用检测,但它不必使用。它可以使用Java平台提供的所有其他功能。不使用检测的代理的典型示例是JMX代理。看看JVisualVM
提供的工具。它的大多数功能(除了分析器)都是通过JMX代理提供的,而不使用仪器。
顺便提一下,关于仪器和类加载器之间差异的问题。自定义类加载器不能更改通过引导类加载器加载的类,如java.lang.Object
(尽管在执行此操作之前应该三思而后行)。此外,您的自定义类加载器必须实现原始的类加载器语义才能工作。否则,例如,如果您尝试使用委托拦截加载,则类加载器将错过JVM尝试解析依赖项时加载的所有类。由应用程序(例如,由RMI)创建的另一个ClassLoader
加载的所有类都不会被您的自定义类加载器处理。
因此,Instrumentation添加了一种独立于ClassLoader
和(可选)处理类的方法,甚至允许在加载后按需更改它们。