Tuesday, February 8, 2011

Groovy Uses JAVA_OPTS

Developers who have used Tomcat in any significant way are likely already familiar with using the environment variable JAVA_OPTS to specify how much memory should be allocated for an instance of Tomcat. The author of CATALINA_OPTS v JAVA_OPTS - What is the difference? points out that JAVA_OPTS may be used by "other applications" and this should be a consideration when deciding whether to use CATALINA_OPTS or JAVA_OPTS. It turns out that Groovy is an example of one of those "other" applications that uses JAVA_OPTS. In this post, I look at some common uses in Groovy for JAVA_OPTS.

Perhaps the most well-known and common use of JAVA_OPTS within Groovy development is for specifying initial and maximum JVM heap sizes used by Groovy scripts and the JVM in which they run. This is specifically mentioned in the Running section of the Getting Started Guide's Quick Start under the heading "Increasing Groovy's JVM Heap Size". There's not much to say here and it's succinctly stated:
To increase the amount of memory allocated to your groovy scripts, set your JAVA_OPTS environment variable. JAVA_OPTS="-Xmx..."

The Groovy Native Launcher page also demonstrates using JAVA_OPTS to specify heap size for a JVM running Groovy under the heading "JAVA_OPTS" and mentions "achieving the same effect" with environmental variable JAVA_TOOL_OPTIONS.

The use of JAVA_OPTS with Groovy is not limited to specifying heap sizes. Indeed, the Native Launcher JAVA_OPTS section states: "The environment variable JAVA_OPTS can be used to set JVM options you want to be in effect every time you run groovy."

Use of JAVA_OPTS in Groovy is not limited to the groovy launcher or to runtime. In the blog post Using groovyc To Compile Groovy Scripts, I discussed several advantages of explicitly using groovyc and one of the advantages I mentioned is the ability to better understand Groovy's inner workings through use of groovyc. JAVA_OPTS can be used in conjunction with groovyc to further this advantage. Specifically, Groovy in Action points out that groovyc "is sensitive to" three properties that can be specified via JAVA_OPTS: antlr.ast=groovy, antlr.ast=html, and antlr.ast=mindmap. I briefly demonstrate using these with groovyc and JAVA_OPTS.

For the examples of using groovyc, JAVA_OPTS, and the "antlr.ast" settings, I will run groovyc against the script findClassInJar.groovy that was introduced in my blog post Searching JAR Files with Groovy. For convenience, I have included that code listing here.

findClassInJar.groovy
#!/usr/bin/env groovy

/**
 * findClassInJar.groovy
 *
 * findClassInJar <<root_directory>> <<string_to_search_for>>
 *
 * Script that looks for provided String in JAR files (assumed to have .jar
 * extensions) in the provided directory and all of its subdirectories.
 */

import java.util.zip.ZipFile
import java.util.zip.ZipException

rootDir = args ? args[0] : "."
fileToFind = args && args.length > 1 ? args[1] : "class"
numMatchingItems = 0
def dir = new File(rootDir)
dir.eachFileRecurse
{ file->
   if (file.isFile() && file.name.endsWith("jar"))
   {
      try
      {
         zip = new ZipFile(file)
         entries = zip.entries()
         entries.each
         { entry->
            if (entry.name.contains(fileToFind))
            {
               println file
               println "\t${entry.name}"
               numMatchingItems++
            }
         }
      }
      catch (ZipException zipEx)
      {
         println "Unable to open file ${file.name}"
      }
   }
}
println "${numMatchingItems} matches found!"

The above script can be run directly without explicitly using groovyc and this is typically how I'd use it. However, I am going to explicitly compile it here to demonstrate using JAVA_OPTS with groovyc.

The first demonstration involves setting JAVA_OPTS to -Dantlr.ast=groovy which Groovy in Action tells us is for "pretty printing." Once the environmental variable is properly set, it is simply a matter of running groovyc. This is shown off in the next screen snapshot which shows just the Groovy script source at first by itself, the setting of JAVA_OPTS, the executing of groovyc, and the generated output files (.class files and the findClassInJar.groovy.pretty.groovy file generated because of the flag passed via JAVA_OPTS (-Dantlr.ast=groovy)).


This can similarly be done with JAVA_OPTS set with -Dantlr.ast=html (generates HTML output) and -Dantlr.ast=mindmap (format used by FreeMind). Doing this for the other two properties is shown in the next screen snapshot.


Besides the normal .class files generated by groovyc, we now have three additional generated artifacts based on the three different antlr.ast settings: findClassInJar.groovy.pretty.groovy (pretty print), findClassInJar.groovy.html (HTML output), and findClassInJar.groovy.mm (Mindmap output). Each of these output formats are focused on next.

The pretty print output attempts to indent and beautify the code to enable a good representation of code's nesting structure. The contents of findClassInJar.groovy.pretty.groovy are shown next:

import java.util.zip.ZipFile
import java.util.zip.ZipException

rootDir = args?args[0]:"."
fileToFind = args && args.length > 1?args[1]:"class"
numMatchingItems = 0
def dir = new File(rootDir)
dir.eachFileRecurse 
{file -> 
if (file.isFile() && file.name.endsWith("jar")) {
    try {
        zip = new ZipFile(file)
        entries = zip.entries()
        entries.each 
        {entry -> 
        if (entry.name.contains(fileToFind)) {
            println file
                println " ${entry.name}"
                    numMatchingItems++
}
}
}












         catch (ZipException zipEx) {
            println "Unable to open file ${file.name}"
}
}
}

The HTML output might be more interesting in some cases. I show findClassInJar.groovy.html as rendered in the Chrome web browser in the next screen image.


This output is not too surprising, but the color syntax is nice and it might be helpful to make Groovy source code available via this mechanism.

The output generated in the form of findClassInJar.groovy.mm is not very useful when viewed directly (it's just some difficult-to-read XML), but is graphically more pleasing when that .mm file is rendered in FreeMind. This is shown in the next screen snapshot.


I still find it difficult to read, but it's darn pretty and likely will impress someone.

As I stated in my post Groovy Scripts Master Their Own Classpath with RootLoader, I often use shell scripts to kick off my Groovy scripts. These shell scripts can do certain things to set up my Groovy environment just how I like it, including specifying the classpath information for the Groovy script and setting JAVA_OPTS appropriately before running the Groovy script and unsetting it (cleaning it out) before terminating.


Conclusion

The JAVA_OPTS environment variable is a useful approach for specifying various JVM options that one wants Groovy scripts to have access to during runtime and for specifying various JVM options that one wants the Groovy compiler to use during compilation. This post has demonstrated use of JAVA_OPTS to specify heap size for a JVM executing Groovy code and to specify to groovyc to generate additional artifacts from Groovy source code.

1 comment:

buddy said...

Thanks for sharing information dude. Didn't know groovy was using JAVA_OPTS.

Thanks
Javin
How HashMap works in Java