Class Agent
- java.lang.Object
-
- com.hapiware.agent.Agent
-
public class Agent extends Object
Agentis a generic solution to greatly simplify the agent programming (seejava.lang.instrumentpackage description for more information about agents in general).The main idea is to have a totally separated environment for running agents. This means that the agent uses its own namespace (i.e. class loader) for its classes. With
Agenta programmer can avoid .jar file version conflicts. That's why theAgentconfiguration file has its ownclasspathelement(s). Another advantage is that the XML configuration file is always similar for different agents. And yet one more advantage is that the programmer does not need to care about the manifest attributes mentioned injava.lang.instrumentpackage description. They are already handled for the programmer.Using
AgentAgentis specified by using Java-javaagentswitch like this:For example:-javaagent:agent-jarpath=path-to-xml-config-file-javaagent:/users/me/agent/target/agent-1.0.0.jar=/users/me/agent/agent-config.xmlConfiguration file
The configuration file is an XML file and has the<agent>as its root element.<agent>has the following childs:<variable>, this is an optional element for simplifying the configuration<delegate>, this is a mandatory element to define the agent delegate-
<classpath>, this is a mandatory element and has at minimum of one (1)<entry>child element. -
<filter>, this is an optional element and can have zero (0)<include>and/or<exclude>child elements. Filters are regular expressions patterns to include or exclude classes to be instrumented. -
<configuration>, which is an optional element is used to configure agent delegate. See/agent/configurationelement
<?xml version="1.0" encoding="UTF-8" ?> <agent> <variable /> <variable /> ... <delegate /> <classpath> <entry /> <entry /> ... </classpath> <filter> <include /> <include /> <exclude /> <exclude /> ... </filter> <configuration> <!-- This can be text, a predefined structure or programmer's own structure --> </configuration> </agent>
The/agent/variableelement/agent/variableelement is optional and it is supposed to be used to simplify the configuration file. Variables can be anywhere underagentelement (i.e. they need not to be in the beginning of the configuration file).The
/agent/variableelement must have (only)nameattribute which is used as a reference in other parts of the configuration file. Thenamereference is replaced by the value of the/agent/variableelement. The variable value can contain variable references which will be resolved in this order :- Variable defined previously
- System property
- Environment variable
${VARIABLE}where:VARIABLEis thenameattribute of the/agent/variableelement
${repo-path}variable reference is replaced with/users/me/.m2/repositorystring:
Variables can be used more creatively if there is a need for that. This example produces exactly the same result than the example above but the use of variables are more complex:<?xml version="1.0" encoding="UTF-8" ?> <agent> <variable name="repo-path">/users/me/.m2/repository</variable> <delegate>com.hapiware.test.MyAgentDelegate</delegate> <classpath> <entry>/users/me/agent/target/my-delegate-1.0.0.jar</entry> <entry>${repo-path}/asm/asm/3.1/asm-3.1.jar</entry> <entry>${repo-path}/asm/asm-commons/3.1/asm-commons-3.1.jar</entry> <entry>${repo-path}/asm/asm-util/3.1/asm-util-3.1.jar</entry> <entry>${repo-path}/asm/asm-tree/3.1/asm-tree-3.1.jar</entry> </classpath> <configuration>...</configuration> </agent><?xml version="1.0" encoding="UTF-8" ?> <agent> <variable name="a">repo</variable> <variable name="b">path</variable> <variable name="c">ju</variable> <variable name="juuri">roo</variable> <variable name="${${c}uri}t">users</variable> <variable name="${a}-${b}">/${root}/me/.m2/repository</variable> <variable name="asm-package">asm</variable> <variable name="${asm-package}-version">3.1</variable> <delegate>com.hapiware.test.MyAgentDelegate</delegate> <classpath> <entry>/users/me/agent/target/my-delegate-1.0.0.jar</entry> <entry>${repo-path}/${asm-package}/asm/${asm-version}/asm-${asm-version}.jar</entry> <entry>${repo-path}/${asm-package}/asm-commons/${asm-version}/asm-commons-${asm-version}.jar</entry> <entry>${repo-path}/${asm-package}/asm-util/${asm-version}/asm-util-${asm-version}.jar</entry> <entry>${repo-path}/${asm-package}/asm-tree/${asm-version}/asm-tree-${asm-version}.jar</entry> </classpath> <configuration>...</configuration> </agent>
The/agent/delegateelement/agent/delegateelement is mandatory and its value is the name of the delegate class as a fully qualified name (e.g.com.hapiware.asm.TimeMachineAgentDelegate).The agent delegate class must have the following method (with the exact signature):
public static void premain( java.util.regex.Pattern[] includePatterns, java.util.regex.Pattern[] excludePatterns, Object config, Instrumentation instrumentation )where:-
java.util.regex.Pattern[] includePatternshas a list of regular expression patterns to be used to include classes for instrumentation. See/agent/filter -
java.util.regex.Pattern[] excludePatternshas a list of regular expression patterns to be used to set classes not to be instrumented. See/agent/filter -
Object configis the configuration object based on the/agent/configurationelement. Instrumentation instrumentationhas services to provide the instrumentation.
static void premain(java.util.regex.Pattern[], java.util.regex.Pattern[], Object, Instrumentation)method can do all the same things as defined forstatic void premain(String, Instrumentation)method in thejava.lang.instrumentpackage description.
The/agent/classpathelement/agent/classpathelement is mandatory and is used to define the classpath for the agent delegate class. This means that there is no need to put any of the used libraries for the agent delegate class in to your environment classpath.The
/agent/classpathelement must have at least one<entry>child element but can have several. The only required classpath entry is the delegate agent (.jar file) itself. However, usually there are other classpath entries for the libraries needed by the delegate agent. Here is an example:<?xml version="1.0" encoding="UTF-8" ?> <agent> <delegate>com.hapiware.agent.TimeMachineAgentDelegate</delegate> <classpath> <entry>/users/me/agent/target/timemachine-delegate-1.0.0.jar</entry> <entry>/usr/local/asm-3.1/lib/all/all-asm-3.1.jar</entry> </classpath> <configuration>...</configuration> </agent>
The/agent/filterelement/agent/filteris optional and is used to filter classes to be instrumented.The
/agent/filterelement can have severalincludeand/orexcludeelements but can have also none of them. Here is an example:<?xml version="1.0" encoding="UTF-8" ?> <agent> <delegate>com.hapiware.test.MyAgentDelegate</delegate> <classpath> <entry>/users/me/agent/target/my-delegate-1.0.0.jar</entry> </classpath> <filter> <include>^com/hapiware/.*f[oi]x/.+</include> <include>^com/mysoft/.+</include> <exclude>^com/hapiware/.+/CreateCalculationForm</exclude> </filter> <configuration>...</configuration> </agent><include>element<include>element can be used for matching the possible candidates for instrumentation. If none is defined then one pattern containing".+"is assumed as a default value.<include>element is a normal Java regular expression.Notice that the class names are presented in the internal form of fully qualified class names as defined in The Java Virtual Machine Specification (e.g. "java/util/List"). So, when you create
<include>and<exclude>elements, remember that package names are separated with slash (/) instead of period (.).<exclude>element<exclude>can be used to ensure that the instrumentation is not done for some classes.<exclude>element is a normal Java regular expression.Notice that the class names are presented in the internal form of fully qualified class names as defined in The Java Virtual Machine Specification (e.g. "java/util/List"). So, when you create
<include>and<exclude>elements, remember that package names are separated with slash (/) instead of period (.).
The/agent/configuration/element/agent/configuration/element is optional and has all the necessary configuration information for the agent delegate class. The exact structure can depend on the programmer but there are some predefined structures as well. The configuration object is delivered to the agent delegate'sstatic void premain(java.util.regex.Pattern[], java.util.regex.Pattern[], Object, Instrumentation)method as anObjectargument.All the possible options for configuration object creation are:
nullStringList<String>Map<String, String>- User defined configuration object
If thenull/agent/configuration/element is not defined at all thennullis delivered to the agent delegate'sstatic void premain(java.util.regex.Pattern[], java.util.regex.Pattern[], Object, Instrumentation)method as anObjectargument. For example:
which sends<?xml version="1.0" encoding="UTF-8" ?> <agent> <delegate>com.hapiware.test.MyAgentDelegate</delegate> <classpath> <entry>/users/me/agent/target/my-delegate-1.0.0.jar</entry> </classpath> </agent>nullto theMyAgentDelegate.premain(java.util.regex.Pattern[], java.util.regex.Pattern[], Object, Instrumentation)method as anObjectargument.
If theString/agent/configuration/element has only pure text (i.e.String), the text string is delivered to the delegate'sstatic void premain(java.util.regex.Pattern[], java.util.regex.Pattern[], Object, Instrumentation)method as anObjectargument. For example:
which sends "Show me!" to the<?xml version="1.0" encoding="UTF-8" ?> <agent> <delegate>com.hapiware.test.MyAgentDelegate</delegate> <classpath> <entry>/users/me/agent/target/my-delegate-1.0.0.jar</entry> </classpath> <configuration>Show me!</configuration> </agent>MyAgentDelegate.premain(java.util.regex.Pattern[], java.util.regex.Pattern[], Object, Instrumentation)method as anObjectargument.
If theList<String>/agent/configuration/element has<item>child elements without an attribute then theList<String>is created which is in turn delivered to the agent delegate'sstatic void premain(java.util.regex.Pattern[], java.util.regex.Pattern[], Object, Instrumentation)method as anObjectargument. For example:
which sends<?xml version="1.0" encoding="UTF-8" ?> <agent> <delegate>com.hapiware.test.MyAgentDelegate</delegate> <classpath> <entry>/users/me/agent/target/my-delegate-1.0.0.jar</entry> </classpath> <configuration> <item>One</item> <item>Two</item> <item>Three</item> </configuration> </agent>List<String>{"One", "Two", "Three"} to theMyAgentDelegate.premain(java.util.regex.Pattern[], java.util.regex.Pattern[], Object, Instrumentation)method as anObjectargument.
If theMap<String, String>/agent/configuration/element has<item>child elements with akeyattribute then theMap<String, String>is created which is in turn delivered to the agent delegate'sstatic void premain(java.util.regex.Pattern[], java.util.regex.Pattern[], Object, Instrumentation)method as anObjectargument. For example:
which sends<?xml version="1.0" encoding="UTF-8" ?> <agent> <delegate>com.hapiware.test.MyAgentDelegate</delegate> <classpath> <entry>/users/me/agent/target/my-delegate-1.0.0.jar</entry> </classpath> <configuration> <item key="1">One</item> <item key="2">Two</item> <item key="3">Three</item> </configuration> </agent>Map<String, String>{{"1", "One"}, {"2", "Two"}, {"3", "Three"}} to theMyAgentDelegate.premain(java.util.regex.Pattern[], java.util.regex.Pattern[], Object, Instrumentation)method as anObjectargument.User defined configuration object
If the/agent/configuration/element has thecustomchild element defined, thenpublic static Object unmarshall(org.w3c.dom.Element configElement)method must be defined to the agent delegate class in addition topremain()method. Theunmarshall()method is called with the/agent/configuration/customelement as an argument. The system then delivers the returnedObjectdirectly to the agent delegate'sstatic void premain(java.util.regex.Pattern[], java.util.regex.Pattern[], Object, Instrumentation)method as anObjectargument. This approach makes it possible to create different configuration structures for the agent delegate'sstatic void premain(java.util.regex.Pattern[], java.util.regex.Pattern[], Object, Instrumentation)method very flexibly.public static Object unmarshall(org.w3c.dom.Element configElement)is assumed to return a programmer's own configuration object. Here is an example:
This assumes that<?xml version="1.0" encoding="UTF-8" ?> <agent> <delegate>com.hapiware.agent.FancyAgentDelegate</delegate> <classpath> <entry>/users/me/agent/target/fancy-delegate-1.0.0.jar</entry> <entry>/usr/local/asm-3.1/lib/all/all-asm-3.1.jar</entry> </classpath> <filter> <include>^com/hapiware/.*f[oi]x/.+</include> <include>^com/mysoft/.+</include> <exclude>^com/hapiware/.+/CreateCalculationForm</exclude> </filter> <configuration> <custom> <message>Hello World!</message> <date>2010-3-13</date> </custom> </configuration> </agent>com.hapiware.asm.FancyAgentDelegateclass haspublic static Object unmarshall(org.w3c.dom.Element configElement)method defined to handle<message>and<date>elements from the<configuration/custom>element. It is also assumed that theObjecttheunmarshall()method returns can be properly handled (and type casted) in thestatic void premain(java.util.regex.Pattern[], java.util.regex.Pattern[], Object, Instrumentation)method.- Author:
- hapi
- See Also:
java.lang.instrument
-
-
Field Summary
Fields Modifier and Type Field Description static StringVARIABLE_PREFIXstatic StringVARIABLE_SUFFIX
-
Constructor Summary
Constructors Constructor Description Agent()
-
Method Summary
All Methods Static Methods Concrete Methods Modifier and Type Method Description static voidpremain(String agentArgs, Instrumentation instrumentation)This method is called before the main method call right after the JVM initialisation.
-
-
-
Field Detail
-
VARIABLE_PREFIX
public static final String VARIABLE_PREFIX
- See Also:
- Constant Field Values
-
VARIABLE_SUFFIX
public static final String VARIABLE_SUFFIX
- See Also:
- Constant Field Values
-
-
Method Detail
-
premain
public static void premain(String agentArgs, Instrumentation instrumentation)
This method is called before the main method call right after the JVM initialisation.Notice that this method follows the fail fast idiom and thus throws a runtime exception if there is something wrong in the configuration file.
- Parameters:
agentArgs- Same string which was given to-javaagentas options (see the class description).instrumentation- Seejava.lang.instrument.Instrumentation- Throws:
com.hapiware.agent.Agent.ConfigurationError- If there is something wrong with the configuration file.- See Also:
java.lang.instrument
-
-