Reflex Usage

Reflex is implemented as a java.lang.instrument agent. Then, a special way to run it is necessary. In this section we will review how to use Reflex, which are the most relevant parameters and how to specify them. Finally, we will see an utility class ReflexRunner that allows us to programatically run Reflex.

Command Line

As mentioned before, in order to run Reflex, a special syntax is needed. The Java agent “specification” forces us to specify a jar path that must contain a META-INF/MANIFEST.MF file, where the name of the class implementing the agent is found. This jar file is reflexagent.jar and is included in the Reflex distribution (lib directory).

An example of the use described above is:

    % java "-javaagent:reflexagent.jar" ...

Parameters that will be passed to this agent must be specified next to the path:

    % java "-javaagent:reflexagent.jar=arg1 arg2" ...

Reflex Arguments

Follow is a partial list of the Reflex's parameters:

  --working-set [<+/-> subset1 <+/-> subset2 ...]
Specifies the set of classes that are elegible for instrumentation.
   Each subset is a colon-separated list of classes or packages.
   For packages, Ant style wildcards are allowed:
   reflex.test.* means all the classes in the reflex.test package
   reflex.test.** means all the classes in reflex.test and its 'subpackages'
   Example:
    [+reflex.tools.*:reflex.test.** -reflex.test.gen.** +reflex.test.gen.TestMain]
    All the classes of reflex.tools are included. All the classes of reflex.test
    and its subpackages are included, except those in reflex.test.gen and 
    subpackages, but reflex.test.gen.TestMain is included.

-linkProviders -lp provider1,provider2,...,providerN
specify link providers from which Reflex obtains the links
to apply to the application

--silent
run Reflex in silent mode

--light
run Reflex in light log level

--verbose
run Reflex in verbose mode

For example, if you want to run the com.test.Application class with “5” as parameter using Reflex in verbose mode, instrumenting only the classes in the com.test package using the com.app.conf.LoggingLinkProvider link provider, the command line should be:

    % java "-javaagent:reflexagent.jar=--verbose   --working-set [com.test.*]  
          -lp   class:com.app.conf.LoggingLinkProvider" com.test.Application 5

As you can see, specifying a command that uses an agent is pretty hard. That is why we provide (and use ourselves) an utility class to run Reflex programatically: ReflexRunner.

ReflexRunner utility class

Basically, this utility class provides means to specify the parameters that will be passed to Java in a programatically way. Then, the responsibility of creating the correct command line is left to this class.

Next we will review the important part of the API of this class.

public ReflexRunner addVMArg(String aKey, String aValue)

This method adds a virtual mechine argument. In other words, an argument to pass to the java executable.

public ReflexRunner setAgentPath(String anAgentPath)

This method specifies where the agent jar is. The default value is lib/reflexagent.jar.

public ReflexRunner addReflexArg(String aKey, String aValue)

This method allows us to specify a Reflex argument, like -lp class:com.app.conf.LoggingLinkProvider.

public ReflexRunner setMainClass(String aMainClass)

This method sets the name of the application class.

public ReflexRunner addAppArgs(String... aArgs)

This method adds a new set of arguments to the application.

Example

To clarify this, let us run the application we saw before using this utility class:

ReflexRunner runner = new ReflexRunner();
 
runner.addReflexArg("--verbose", null);
runner.addReflexArg("--working-set", "[com.test.*]");
runner.addReflexArg("-lp", "class:com.app.conf.LoggingLinkProvider");
 
runner.setMainClass("com.test.Application");
runner.addAppArgs("5");
 
ReflexRunner.RunningReflexInstance instance = runner.runReflex(true);
theInstance.waitFor();   //Waits for the application

The last two lines of the previous example creates a new java process and waits for its exit respectively. Note that using this approach you can launch several instances of your application and then monitor them using the RunningReflexInstance instances.

At the moment, RunningReflexInstance has two methods to interact with the lauched application: finish and finishedNormally, that forces to finish the application and asks whether it finished normally respectively.

In the remaining chapters of the tutorial, we will use an ExamplesRunner class that is based on this.