There are three questions that developers commonly ask when developing and running Java in the fabric:
What JVM will be used to run my Java code and what control do I have over the selection?
What arguments are passed to the JVM and do I have any control over it?
How can I add jars to my classpath?
The fabric will load a Java Virtual Machine (JVM) for each fabric application that requires Java (i.e., the application has user code that is written in Java). The fabric_pkg command also starts a JVM during packaging in order to validate an application that uses Java. Under most circumstances, the JVM from the correct Java installation will be used. See Locating the Java Virtual Machine for details. The arguments used to start the JVM are specified in the fabric.cfg. Changes to the Java settings in the fabric.cfg affect how all JVMs in the fabric are started. Optionally, each application can control the arguments passed to its JVM using the Application Configuration File.
Each application gets its own URLClassLoader. The list of URLs (e.g., jars) given to this class loader can come from a number of sources:
the primary set of jars for the class loader are derived from the Fabric Application Definition XML, where it can list the jars on which it depends.
the application can also list fars on which it is dependent. Jars included by the far are added to the classpath of each application that depends on the far.
To provide Java support, the fabric must locate and load a libjvm.so (jvm.dll on Windows). To control which JVM gets loaded, use one of the following methods.
define JAVA_HOME to point to the version you would like used (Note: remember that environment changes are seen by Windows services only after a reboot),
change the CurrentVersion in the Windows registry (Windows only), or
Note: the order of the list is important - if JAVA_HOME is defined, changing the registry or /usr/java will not have an affect on which JVM is used. The following strategy is used when locating a JVM:
The fabric will first check for the environment variable JAVA_HOME:
empty (or invalid) installations are ignored,
preference is given to the server JVM (%JAVA_HOME%\jre\bin\server\jvm.dll on windows, and $JAVA_HOME/jre/lib/i386/server/libjvm.so on linux) when JAVA_HOME is a JDK installation.
If the JVM wasn't found using JAVA_HOME, the fabric will check the windows registry (Windows only):
if there is a current version of the JDK installed (using registry value CurrentVersion under JKLM\SOFTWARE\JavaSoft\Java Development Kit), and the JavaHome registry value of the current version points to a valid JDK directory, the jre/bin/server/jvm.dll from that installation will be used.
if there is a current version of the JRE installed (using registry value CurrentVersion under JKLM\SOFTWARE\JavaSoft\Java Runtime Environment), then the RuntimeLib registry value of the current version will be used as the JRE.
If the JVM wasn't found using JAVA_HOME, the fabric will try to locate a default installation (Linux only):
if /usr/java/default exists and is a valid JDK or JRE installation, a JVM will be located from the folder using the JAVA_HOME logic.
otherwise, the folder in /usr/java containing the highest JDK or JRE version will be selected and a JVM will be located from that folder using the JAVA_HOME logic.
empty folders are ignored,
preference is given to a JDK installation over a JRE, and
preference is given to a server JVM over a client JVM.
Finally, if no JVMs have been located, an attempt is made to load one from the path (PATH on Windows and LD_LIBRARY_PATH on Linux).
Java Virtual Machine Arguments
The fabric.cfg file contains a single required property fabric-jvm-options that specifies the arguments that are used to start JVMs on the fabric. The property is a single, space-delimited, line of arguments. The initial value for this property is -Xrs -Djava.class.path=${FABRIC_HOME}/classes/fabric.jar. Changes to this property will affect all JVMs started in the fabric. This property has two required entries:
the signal handling option -Xrs must be included - it is critical for proper fabric operations, and
the system class loader must be able to find the classes in fabric.jar.
Appistry recommends:
any fabric-wide JVM arguments (e.g., memory options) be appended to this property
do not add application-specific jars to the classpath in the fabric.cfg file - use one of the other options that affect the class loader as described below.
The following example fabric.cfg shows how to change heap allocation and enable writing heap to a file when OutOfMemoryError exception is thrown:
Adding jars to the classpath of all fabric applications
In some cases, a user may install jars in the image of each fabric worker that are needed by all or most of the user's applications running on the fabric. These jars can be added to the fabric.cfg file using the property fabric-additional-user-classpath, separated by the fabric-additional-user-classpath-separator. Each archive listed will be added to each fabric applications' URLClassLoader list.
The following example fabric.cfg adds two jars to the class loader of all applications in the fabric:
The list of jars added to the class loader of the application is also affected by jars mentioned in the application definition XML and jars mentioned in any Far files referenced by the application. Appistry recommends the use of Far files when sharing jars between applications due to the ability to version and deploy Fars separately from applications (see Fabric Archives for more details).
In any case, the fabric-additional-user-classpath should be limited to jars whose version is changed by re-imaging the worker. For example, if jars are stored in each worker's image, and not deployed and versioned as resources in the fabric, then you would use the fabric-additional-user-classpath to add these jars to fabric applications. Typically, the recommendation would be to deploy the jars either in a versioned Far file, or included in a versioned fabric application.
Controlling JVM arguments for a single fabric application