agent-embedder:embed
Full name:
dev.aspectj:agent-embedder-maven-plugin:1.0:embed
Description:
Embeds one or more java agents into the module's main artifact
Use this goal, if (and only if) you have an executable JAR (with a Main-Class
attribute in its manifest) and wish to run a java agent automatically when running the JAR with java -jar my.jar
on JRE 9+.
Normally, you would need an additional -javaagent:/path/to/agent.jar
JVM argument, but since Java 9 there is the Launcher-Agent-Class
mechanism. I.e., even though this plugin works just fine on Java 8, you do need to launch the modified executable JAR on JRE 9+ to enjoy the benefits of this JVM feature.
The javaAgents
specified for this goal will be unpacked from their JARs and embedded into the main artifact's root directory to make them visible to the java agent classloader during runtime. JVM classloaders cannot load agents from nested JARs.
The main artifact is expected to exist already when executing this goal. Typically, the Maven module already uses another plugin creating a build artifact during the package
phase, which is why this goal by default also runs in the same phase. Make sure to configure this plugin to run after the plugin creating the main artifact, so you have something for it to operate on. This can be done most easily by simply listing both plugins in the POM file in the desired chronological execution order, if they are to run in the same phase. Another option would be to let them run in different phases, making sure that this plugin runs later than the one creating the artifact. We recommend to stick to convention over configuration and use the package
phase. For example:
<!-- Create executable Spring Boot fat JAR -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Embed Java agent(s) for automatic execution -->
<plugin>
<groupId>dev.aspectj</groupId>
<artifactId>agent-embedder-maven-plugin</artifactId>
<executions>
<execution>
<id>embed-agents</id>
<goals>
<goal>embed</goal>
</goals>
<configuration>
<javaAgents>
<!-- ... -->
</javaAgents>
<removeEmbeddedAgents>true</removeEmbeddedAgents>
</configuration>
</execution>
</executions>
</plugin>
Unique features not offered by the Java 9+ Launcher-Agent-Class
mechanism:
- Via
Launcher-Agent-Class
, the JVM only supports a single agent for auto-start, not multiple ones. Multiple agents can only be specified on the JVM command line. But this plugin installs its own launcher agent, which in turn is capable of starting multiple java agents. Launcher-Agent-Class
also does not support agent option strings like the JVM command line does. This plugin, however, does support agent arguments via its launcher agent. See thejavaAgents
section for more details.
Attributes:
- Requires a Maven project to be executed.
- Requires dependency resolution of artifacts in scope:
compile+runtime
. - The goal is thread-safe and supports parallel builds.
- Binds by default to the lifecycle phase:
package
.
Required Parameters
Name | Type | Since | Description |
---|---|---|---|
<javaAgents> |
List<JavaAgentInfo> |
- |
Java agents to embed into the main artifact
Class
This is an agent with dummy Maven coordinates and an agent path relative to the module base directory:
<javaAgents> <agent> <groupId>dummy</groupId> <artifactId>dummy</artifactId>} <agentPath>${project.basedir}/lib/agent.jar</agentClass> </agent> </javaAgents>This is an agent with dummy Maven coordinates and an agent path inside the executable JAR, plus an option string:
|
<removeEmbeddedAgents> |
boolean |
- |
Remove nested agent JARs from the executable JAR after unpacking their contents into the executable JAR
Some executable JARs contain nested dependency JARs. For example, Spring Boot executable JARs contain some or all of their classpath dependencies in folder BOOT-INF/lib, from where they are loaded using a special classloader that can read nested JARs. Agent JARs defined as dependencies, e.g. aspectjweaver-x.y.z.jar, can also be found there, if the user did not exclude them during the build. After having expanded an agent JAR into the containing JAR's root folder, the classes exist twice in the same JAR - unpacked and as a nested JAR. This is not necessarily a big problem, but bloats the JAR. This option, if active, makes the plugin search for nested JARs matching the names of artifacts described by Default: false |
Parameter Details
<javaAgents>
Class JavaAgentInfo
describes the properties available for describing artifacts. The following properties are available:
groupId
,artifactId
,classifier
: A java agent's Maven coordinates (withoutversion
), which are used to match a dependency declared for the module executing the plugin. If for any reason declaring the agent JAR a dependency is not an option, which should rarely be the case, seeagentPath
for a possible workaround.agentClass
: The agent class containing apremain
launcher method. This property is optional, because by default the plugin extracts the value from the agent JAR'sAgent-Class
manifest attribute. In the rare occasion that you wish to override the manifest value (e.g., the manifest does not exist or does not contain the correct value), set this property.agentArgs
: An optional argument string for the java agent. When using-javaagent
on the JVM command line, an argument string is specified after an equals sign, e.g.-javaagent:/path/to/agent.jar=option1=one,option2=two
. This simply maps to anagentArgs
value ofoption1=one,option2=two
.agentPath
: Usually, the agent path is inferred from the corresponding dependency described by configuration valuesgroupId
,artifactId
,classifier
. This works for regular dependencies as well as system-scoped ones. But maybe, you have a special case where e.g. the agent JAR is stored in a libraries directory checked into the project's SCM (source code management) system. (Please, avoid working like that!) Then, you can specifyagentPath
to point there. Another case is that you know the path of a nested agent JAR inside the main artifact, e.g. BOOT-INF/lib/agent.jar, and for some weird reason the JAR got there without being a dependency. Again, you can specifyagentPath
to point there. The plugin will find and unpack the JAR from there.
<javaAgents>
<agent>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</agent>
<agent>
<groupId>dev.aspectj</groupId>
<artifactId>remove-final-agent</artifactId>
<!-- Optional parameter, overriding agent manifest value -->
<agentClass>dev.aspectj.agent.NonManifestRemoveFinalAgent</agentClass>
<agentArgs>dev.aspectj.FirstComponent,dev.aspectj.SecondComponent</agentArgs>
</agent>
</javaAgents>
This is an agent with dummy Maven coordinates and an agent path relative to the module base directory:
<javaAgents> <agent> <groupId>dummy</groupId> <artifactId>dummy</artifactId>} <agentPath>${project.basedir}/lib/agent.jar</agentClass> </agent> </javaAgents>This is an agent with dummy Maven coordinates and an agent path inside the executable JAR, plus an option string:
<javaAgents>
<agent>
<groupId>dummy</groupId>
<artifactId>dummy</artifactId>
<agentPath>BOOT-INF/lib/agent.jar</agentClass>
<agentArgs>option1=one,option2=two</agentArgs>
</agent>
</javaAgents>
- Type:
java.util.List<dev.aspectj.maven.agent_embedder.JavaAgentInfo>
- Required:
Yes
<removeEmbeddedAgents>
Some executable JARs contain nested dependency JARs. For example, Spring Boot executable JARs contain some or all of their classpath dependencies in folder BOOT-INF/lib, from where they are loaded using a special classloader that can read nested JARs. Agent JARs defined as dependencies, e.g. aspectjweaver-x.y.z.jar, can also be found there, if the user did not exclude them during the build. After having expanded an agent JAR into the containing JAR's root folder, the classes exist twice in the same JAR - unpacked and as a nested JAR. This is not necessarily a big problem, but bloats the JAR.
This option, if active, makes the plugin search for nested JARs matching the names of artifacts described by javaAgents
. For each agent, the first nested JAR found is deleted.
- Type:
boolean
- Required:
Yes
- Default:
false