Niklas Herder
Niklas Herder

Reputation: 131

Specify java agent inside 'fat jar'?

I am using the jetty-alpn-agent to add ALPN support to my project, but all I can find is instructions on how to run it from the .m2 folder, which makes me need to deploy two jar:s instead of just my one uber-jar, making it less portable.

Is is possible to specify a location inside the jar to the -javaagent switch?

I'm looking for something like java -javaagent:my.jar!/javaagents/jetty-alpn-agent-2.0.0.jar -jar myjar.jar, but that doesn't seem to work.

Upvotes: 10

Views: 2660

Answers (2)

Rafael Winterhalter
Rafael Winterhalter

Reputation: 43997

You can emulate the previous agent by writing the premain class into your fat jar's manifest. Then, simply add your fat jar both via the javaagent and and as the jar argument.

It is not possible to avoid this as the instrumentation API is quite powerful and allows to avoid a security manager what would offer an entry point for an attack. You can however self-attach on a JDK or a Java 9 VM. The byte-buddy-agent library offers a ready-made dependency for this. This way, you can invoke your premain method manually after getting hold of an instrumentation instance.

Upvotes: 1

René Link
René Link

Reputation: 51343

It might be possible according to the java.lang.instrumentation documentation.

If the implementation allows it the jetty-alpn-agent.jar must be part of the system classpath. So you must include it in your my.jar like any other application library.

Starting Agents After VM Startup

An implementation may provide a mechanism to start agents sometime after the the VM has started. The details as to how this is initiated are implementation specific but typically the application has already started and its main method has already been invoked. In cases where an implementation supports the starting of agents after the VM has started the following applies:

The manifest of the agent JAR must contain the attribute Agent-Class. The value of this attribute is the name of the agent class.

The agent class must implement a public static agentmain method.

The system class loader ( ClassLoader.getSystemClassLoader) must support a mechanism to add an agent JAR file to the system class path.

The agent JAR is appended to the system class path. This is the class loader that typically loads the class containing the application main method. The agent class is loaded and the JVM attempts to invoke the agentmain method. The JVM first attempts to invoke the following method on the agent class:

public static void agentmain(String agentArgs, Instrumentation inst);

If the agent class does not implement this method then the JVM will attempt to invoke:

public static void agentmain(String agentArgs);

The agent class may also have an premain method for use when the agent is started using a command-line option. When the agent is started after VM startup the premain method is not invoked.

The agent is passed its agent options via the agentArgs parameter. The agent options are passed as a single string, any additional parsing should be performed by the agent itself.

The agentmain method should do any necessary initialization required to start the agent. When startup is complete the method should return. If the agent cannot be started (for example, because the agent class cannot be loaded, or because the agent class does not have a conformant agentmain method), the JVM will not abort. If the agentmain method throws an uncaught exception it will be ignored.

PS: I have never tried this. Please let me know if it works or not.

Upvotes: 2

Related Questions