JavaCOP Tutorial (using Java commands)

Contact Shane Markstrum (smarkstr at cs dot ucla dot edu) with any questions or comments.

How to run JavaCOP as an extensible type checking compiler

Using JavaCOP is relatively as easy as using javac. In fact, JavaCOP is simply an extension of the OpenJDK version of javac. We have a newer tutorial focusing on the use of scripts we have provided for use with JavaCOP. However, if you prefer to learn the basic Java commands to use for running JavaCOP from its jar file, then this tutorial should provide you with the know-how.

First Steps:

  1. Obtain a copy of the JavaCOP jar from the SourceForge site, which includes all components of JavaCOP discussed on the JavaCOP website except for scripts and examples.

  2. Run the JavaCOP Compiler with the -version flag and look for the output show below.

    Linux/Windows:
    prompt> java -cp JavaCop.jar com.sun.tools.javac.Main -version
    javac 1.7.0-ea_JavaCOP
    

    Mac OS X*:
    *Note that there is an error here! Well, that's because the OS X Java and the OpenJDK don't always play the same way with the classpath.
    prompt> java -Xbootclasspath/p:JavaCop.jar com.sun.tools.javac.Main -version
    compiler message file broken: key=javac.version arguments=javac, 1.7.0-ea_JavaCOP, {2}, {3}, {4}, {5}, {6}, {7}
    

  3. You're ready to start using the JavaCOP utilities! Note that you will need to make sure the JavaCop.jar file is available on the classpath for all of the remaining section. This requirement is reflected in JavaCop.jar being shown explicitly on the classpath of all further Java commands.

Compiling JavaCOP Rules

If you are eager to start type checking Java programs with JavaCOP, then this section is optional so long as you download NonnullRules.jar. (This jar file contains all of the necessary Java classes and annotations for checking programs with a non-null type system developed in JavaCOP.) Skip to next section

This section will teach you how to go from a JavaCOP rule file to a compiled JavaCOP checker which can be utilized by the JavaCOP compiler. If you are interested in learning how to write rules, you can visit the rule development section of the main tutorial.

  1. Obtain a copy of the JavaCOP Rule Examples and untar it. Go to the examples/nonnull directory. You should see two subdirectories here (javacop and tests) and the file Nonnull.jcop.

  2. Nonnull.jcop is the file that contains the rule specification for a flow-sensitive non-null checker written in JavaCOP. The first step to creating a type-checking class is to compile the rule specification into a Java file. This is accomplished with the JavaCOP parser.

    prompt> java -cp JavaCop.jar compiler.JcopParser Nonnull.jcop
    Compiling file to: Nonnull.java
    done
    

  3. At this point, there should now be another file in the examples/nonnull directory: Nonnull.java. This file should now be compilable with javac to produce the non-null type checker. Since the checker is an extension of a class from the JavaCOP compiler, you will need JavaCop.jar on your compilation classpath. It also depends on the classes NonNullFlowFacts and RawTypesFlowFacts, which are in the examples/nonnull/javacop/nonnull directory. Including the current working directory in your javac classpath should compile these classes, as well.

    prompt> javac -cp JavaCop.jar:. -d . Nonnull.java
    
    

  4. Now, in the examples/nonnull/javacop/nonnull directory, you should have four Java class files: Nonnull.class, Nonnull$1.class, NonNullFlowFacts.class, RawTypesFlowFacts.class. If compilation has succeeded, then you now have a working copy of the flow-sensitive non-null type checker. The checker can now be used by putting the examples/nonnull directory on the classpath of a JavaCOP compiler invocation and specifying javacop.nonnull.Nonnull as an option. The next section will go into further details of how to type check Java programs.

Type Checking Java Files

At this point, you should have either a jar file or directory structure which you can specify on the classpath of an invocation of the JavaCOP compiler which contains the classes for the flow-sensitive type checker. In all commands from this point, I will be using the placeholder NonnullRules.jar to represent this classpath entry, such as:

prompt> java -cp JavaCop.jar:NonnullRules.jar com.sun.tools.javac.Main ...
  1. Before you can type check a Java file, you will need a file that exercises the pluggable type system which you will load. In this case, we will make a very simple Java class that has one field annoted as non-null and which assigns into that field a new Object instance. Save this class as TutorialClass.java
    import javacop.annotations.Nonnull;
    
    public class TutorialClass {
    
    	@Nonnull Object f;
    	
    	public TutorialClass() {
    		f = new Object();
    	}
    }
    

  2. Now, if you invoke the JavaCOP compiler to compile TutorialClass.java and pass javacop.nonnull.Nonnull as an argument to the -javacop option, it should compile without an error.*
    *Mac users will need to invoke the compiler as previously specified at the beginning of the tutorial.
    java -cp JavaCop.jar:NonnullRules.jar com.sun.tools.javac.Main -javacop javacop.nonnull.Nonnull TutorialClass.java
    Loading constraints class: javacop.nonnull.Nonnull
    Done, loaded 1 constraint sets.
    

  3. To create an error in TutorialClass, change the line
    f = new Object();
    to the line
    f = null;

  4. Now, rerun the JavaCOP compiler and it will report an error.
    java -cp JavaCop.jar:NonnullRules.jar com.sun.tools.javac.Main -javacop javacop.nonnull.Nonnull TutorialClass.java
    Loading constraints class: javacop.nonnull.Nonnull
    Done, loaded 1 constraint sets.
    TutorialClass.java:8: Nonnull: Using possibly null value where a @Nonnull value is expected
                    f = null;
                        ^
    1 error
    

That's all there is to using JavaCOP. It can act as a javac replacement in your toolchain or as a supplement. One thing to note is that the JavaCOP compiler is based on the OpenJDK compiler, which is currently at version 1.7. To run any classes compiled with the JavaCOP compiler, you will need to target the compilation to a version of Java compatible with your java executable.

Return to main tutorial page