Skip to content

Generating and executing Java

Philip Stoev edited this page Aug 29, 2014 · 3 revisions

Introduction

Frizzante is able to generate and run Java methods. Because Java compilation is slow, Frizzante comes with a JavaBatchCompiler that takes certain measures to avoid a situation where most of CPU time is spent compiling Java rather than executing it:

  • Java methods are generated and compiled in batches of 100, thus avoiding compiler overhead;
  • The methods are cached to avoid recompilation if the same method is generated again;

Preparing the grammar

Since Java statements are terminated with a semicolon, which is a special character in Frizzante, the grammar needs to be declared as follows:

#option STANDALONE_SEMICOLONS

and optionally also:

#option TRAILING_PIPES

This way semicolons will only be considered rule terminators if they are alone on a line, and will be passed verbatim into the output otherwise. Pipes will be considered rule production separators only if they are at the end of the line.

Grammar Example

#option STANDALONE_SEMICOLONS
main:
        public static void run() {
                body1 | body2
        }
;

body1:
        System.out.println("foo");
;

body2:
        System.out.println("bar");
;

Execution

If your Java method does not take an argument or use imports, like the run() method above, you can use the JavaBatchRunnableFactory class directly.

java -jar ./target/fuzzer-0.1-jar-with-dependencies.jar --grammar java.grammar --runnableFactory org.stoev.fuzzer.JavaBatchRunnableFactory

Because the Java compiler uses soft references internally, it tends to fill up available memory before beginning massive garbage collections which in turn cause the JVM to grind to a halt. To ensure a smoother running for your test, you may wish to use the following options:

java -XX:SoftRefLRUPolicyMSPerMB=1 -Xincgc -server -jar ...

Frizzante's JavaBatchCompiler uses soft references to cache compiled methods in memory in order to avoid recompiling them every time. In order to avoid filling up memory, it is recommended that you use --range to limit the number of distinct pieces of code that Frizzante will generate.

java -jar ./target/fuzzer-0.1-jar-with-dependencies.jar --range 10000

If your Java method must be passed arguments, subclass JavaBatchRunnableFactory as is done for example in FoundationDBRunnableFactory.java. You will need to override getHeaders() and invoke().

Clone this wiki locally