The generated classes can be debugged interactively, even though they're created on-the-fly.
All that needs to be done is set two system properties, e.g. when starting the JVM:
(The second property is optional; if not set, then the temporary files will be created in the default temporary-file directory.)
When JANINO scans an expression, script, class body or compilation unit, a copy of the source code is stored in a temporary file which the debugger accesses through its source path. (The temporary file will be deleted when the JVM terminates.)
Then when you debug your program
, you can step right into the generated code
, and debug it:
As you can see, you can even inspect and modify fields and variables - everything your debugger supports.
The JavaSourceClassLoader extends JavaTM's java.lang.ClassLoader class with the ability to load classes directly from source code.
To be precise, if a class is loaded through this ClassLoader, it searches for a matching ".java" file in any of the directories specified by a given "source path", reads, scans, parses and compiles it and defines the resulting classes in the JVM. As necessary, more classes are loaded through the parent class loader and/or through the source path. No intermediate files are created in the file system.
If the JavaTM source is not available in files, but from some other storage (database, main memory, ...), you may specify a custom ResourceFinder instead of the directory-based source path.
If you have many source files and you want to reduce the compilation time, you may want to use the CachingJavaSourceClassLoader, which uses a cache provided by the application to store class files for repeated use.
A BASH shell script named "bin/janino" is provided that wraps the JavaSourceClassLoader in a JAVAC-like command line interface:
Janino as a Command-Line JavaTM Compiler
The Compiler class mimics the behavior of SUN's javac tool. It compiles a set of "compilation units" (i.e. JavaTM source files) into a set of class files.
Using the "-warn" option, Janino spits out some probably very interesting warnings which may help you to "clean up" the source code.
The BASH script "bin/janinoc" implements a drop-in replacement for SUN's JAVAC utility:
Janino as an ANT Compiler
Janino as a TOMCAT Compiler
If you want to use JANINO with TOMCAT, just copy the "janino.jar" file into TOMCAT's "common/lib" directory, and add the follwing init parameter section to the JSP servlet definition in TOMCAT's "conf/web.xml" file:
Janino as a Code Analyser
Apart from compiling JavaTM code, JANINO can be used for static code analysis: Based on the AST ("abstract syntax tree") produced by the parser, the Traverser walks through all nodes of the AST, and derived classes can do all kinds of analyses on them, e.g. count declarations:
This is the basis for all these neat code metrics and style checking.
Janino as a Code Manipulator
If, e.g., you want to read a JavaTM compilation unit into memory, manipulate it, and then write it back to a file for compilation, then all you have to do is:
The UnparseVisitor class demostrates how to do this.
Alternative Compiler Implementations
JANINO can be configured to use not its own Java™ compiler, but an alternative implementation. Alternative implementations must basically implement the interface ICompilerFactory. One such alternative implementation is based on the javax.tools API (available since JDK 1.6), and is shipped as part of the JANINO distribution:
Basically there are two ways to switch implementations:
org.codehaus.commons.compiler.jdk.ExpressionEvaluatorand consorts instead of
janino.jaron your compile-time and runtime classpath. (
commons-compiler.jarmust always be on the classpath, because it contains the basic classes that every implementation requires.)
org.codehaus.commons.compiler.CompilerFactoryFactory.getDefaultFactory().newExpressionEvaluator()and compile only against
commons-compiler.jar(and no concrete implementation). At runtime, add one implementation (
commons-compiler-jdk.jar) to the class path, and
getDefaultFactory()will find it at runtime.