|
||||||
Using JVM instrumentation to create a Spring Context Loader Agent for standalone appsWithin the JEE platform a rather common and well-understood system of configuration is based on the Chain of Responsibility and the Event Delivery patterns: the life cycle of enterprise components starts with achieving a general configuration goal. However, on top of this goal, the system defines a number of pre-goals that the system must achieve in combination with an event system that allows configurable actions to be undertaken when the system tries to achieve a pre-goal or the final goal. A typical example is the configuration and starting of a servlet. The servlet is configured in a configuration file and the servlet container reads this file, instantiates and initializes the servlet and puts it in the wait state, waiting for requests. But there is more involved: init parameters are set and the servlet context is initialized. Each step generates a runtime event that listeners can listen for and respond to. The standard configuration of the Spring context in JEE web applications uses this model to load context files through the The Java Instrumentation API on the other hand is not nearly as well-understood or even as well known. Yet it makes it possible to instrument each and every Java program with a similar Chain of Responsibility mechanism as the JEE standards provide out of the box. The mechanism is used by debuggers and frameworks like AspectJ that have to make just-in-time adjustments to classes as they are loaded. As a small introduction this article examines the creation of a Spring context loader mechanism for standalone Java Apps. This mechanism is, in truth, not very useful. But it’s a simple and effective exercise to learn the technique.
Instrumentation basicsInstrumentation in the JVM has been designed using the Chain of Responsibility pattern. In the “classic” Java standalone program, the entry point into the program is the
The sequence diagram above shows the instrumentation mechanism in action: before entering the The You see, where the An exampleAs an example of building a simple agent, let’s create an analog to the Spring ContextLoaderListener for JEE Web applications: a SpringContextLoaderAgent that reads some context files to create an
import java.lang.instrument.Instrumentation;
public class SpringContextLoaderAgent
{
public static void premain(final String agentArgs, final Instrumentation inst)
{
}
}
Creating an application context is not that different: we can just instantiate an
import java.lang.instrument.Instrumentation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringContextLoaderAgent
{
private static ApplicationContext applicationContext;
public static void premain(final String agentArgs, final Instrumentation inst)
{
String[] contextFiles = null;
if (agentArgs != null && agentArgs.contains(","))
{
contextFiles = agentArgs.split(",");
} else
{
contextFiles = new String[] { agentArgs };
}
SpringContextLoaderAgent.applicationContext = new ClassPathXmlApplicationContext(contextFiles);
}
public static ApplicationContext getApplicationContext()
{
return SpringContextLoaderAgent.applicationContext;
}
}
Instrumenting the JVMSo, with the agent written, there’s one thing left to do: getting the JVM to make use of the agent. Explaining to the JVM what you want it to do is a two-step process:
The manifest fileAs you probably know, you can create an executable JAR file by including a manifest file that identifies the class with the Invoking the JVMOnce your agent JAR is ready, you still have to invoke the JVM. To include one agent, use the -javaagent command line switch when invoking the JVM; append that with a colon and the full path of your agent jar. For instance:
In order to pass in command line arguments to the agent, append them to the switch like so:
In order to have multiple agents invoked, use multiple -javaagent switches. The agents will be invoked in the order of the command-line switches. Advanced agentsThis article only demonstrates the basics of creating an agent. However, an agent is capable of some remarkable and powerful things. Specifically, the instrumentation spec allows agents to load, reload, transform and retransform classes. For instance, agents can dynamically rewrite JVM bytecodes to include debugging markers or Clover-style position markers. The AspectJ framework uses the agent instrumentation mechanism for load-time aspect weaving. Agents also don’t have to kick in at launch time: instrumentation implementations can allow agents to launch at runtime in the middle of a program run. Note that this must be signalled in the manifest as well. ConclusionThis article has covered the basics of creating agents to instrument the JVM. It also includes an example of a very simple agent to load Spring contexts for an application. 1 comment to Using JVM instrumentation to create a Spring Context Loader Agent for standalone apps |
||||||
|
Copyright © 2010 Gridshore - All Rights Reserved |
||||||
[...] the ability to inject dependencies to unmanaged classes, is by instrumentation. Ben has written an article about how this works. Spring offers a JAR file that does the proper JVM instrumentation to allow [...]