AREX 启动过程
通用 Java Agent 的启动过程
Java Agent 是一种 Java 应用程序,它可以在 Java 应用程序启动时动态地注入到 JVM 中,并在应用程序运行时监视和修改应用程序的行为。Java Agent 通常用于性能分析、代码覆盖率、安全检查等方面。
以下是 Java Agent 的启动过程:
-
编写 Java Agent 程序,实现
premain
方法。premain
方法是 Java Agent 的入口方法,它会在 Java 应用程序启动时被调用。在premain
方法中,可以进行一些初始化操作,如设置代理、加载配置文件等。 -
将 Java Agent 打包成 jar 文件,并在 MANIFEST.MF 文件中指定
Premain-Class
属性,该属性指定了 Java Agent 的入口类。 -
在启动Java应用程序时,通过 -javaagent 参数指定 Java Agent 的 jar 文件路径。例如:
java -javaagent:/path/to/agent.jar -jar myapp.jar
在上面的命令中,/path/to/agent.jar 是 Java Agent 的 jar 文件路径,myapp.jar 是 Java 应用程序的 jar 文件路径。
-
当 Java 应用程序启动时,JVM 会加载 Java Agent 的 jar 文件,并调用
premain
方法。在premain
方法中,Java Agent 可以使用 Java Instrumentation API 来修改 Java 应用程序的字节码,实现对应用程序的监视和修改。
AREX 源码视角的启动过程
步骤一
在arex-agent module
的pom.xml
文件中,通过配置manifestEntries
,将Premain-Class
属性设置为io.arex.agent.ArexJavaAgent
。这意味着在构建arex-agent.jar
时,将在manifest
文件中指定ArexJavaAgent
类作为 Agent 的入口点。
步骤二
在ArexJavaAgent
类中,实现了premain
方法作为Agent的入口方法。在premain
方法中,它调用了agentmain
方法。在agentmain
方法中,进一步调用了init(Instrumentation inst, String agentArgs)
函数。这个函数接受一个Instrumentation
对象和一个字符串参数agentArgs
。
步骤三
在init
函数中,有两个重要的操作:installBootstrapJar()
和AgentInitializer.initialize()
。
installBootstrapJar()
installBootstrapJar()
函数根据AgentInitializer.class
找到其所在的 jar 包,并通过调用inst.appendToBootstrapClassLoaderSearch(jar)
将其添加到Bootstrap ClassLoader的搜索路径中。Bootstrap ClassLoader是Java虚拟机中负责加载核心类库(如java.lang
和java.util
等)的特殊类加载器。通过调用appendToBootstrapClassLoaderSearch
方法,可以将自定义的类库添加到Bootstrap ClassLoader的搜索路径中,从而使得Java应用程序能够使用这些自定义的类库。
如要根据 class 对象或者 jar 包的实现,获取一个类所在的 jar 包,可以按照以下步骤进行:
- 获取该类的
Class
对象。 - 调用
Class
对象的getProtectionDomain()
方法获取该类的ProtectionDomain
对象。 - 调用
ProtectionDomain
对象的getCodeSource()
方法获取该类的CodeSource
对象。 - 调用
CodeSource
对象的getLocation()
方法获取该类所在的jar包的URL。 - 通过URL对象的
getFile()
方法获取该jar包的路径。
AgentInitializer.initialize()
AgentInitializer.initialize()
函数是根据ArexJavaAgent.class
找到其所在的jar包(AgentInitializer.java
文件),然后设置arex.agent.jar.file.path
变量,即代理jar包所在的目录。
接下来,它会在该目录下查找/extensions/
子目录,并读取该目录下的所有jar包文件,这些文件是扩展包所在的位置。
然后,调用createAgentClassLoader(agent jar, 扩展包.jar)
函数,创建一个AgentClassLoader
对象,它是AREX自定义的类加载器。使用自定义的类加载器是为了隔离,防止应用程序能够访问AREX Agent的代码。
接着,调用createAgentInstaller()
函数,该函数使用前面生成的Ag