tags:

views:

161

answers:

2

I'm trying to understand JavaCompiler.getTask(). I understand all the parameters except for the second to last one called classes. The Javadoc read:

class names (for annotation processing), null means no class names

but I don't understand what they mean. I found plenty of websites referring to JavaCompiler online, but none of them explain this parameter. Any ideas?

+1  A: 

I believe this can be used when you want to run annotation processors on binaries. The classes would be the types you want to process.

Demo code:

public class MyProcessor extends AbstractProcessor {

  public static @interface X { String value(); }

  @X("Hello") public static class Y {}

  @Override public boolean process(Set<? extends TypeElement> annotations,
      RoundEnvironment roundEnv) {
    for (Element element : roundEnv.getRootElements()) {
      X x = element.getAnnotation(X.class);
      if (x != null) System.out.println(x.value());
    }
    return true;
  }

  @Override public Set<String> getSupportedAnnotationTypes() {
    return new HashSet<String>(Arrays.asList(X.class.getCanonicalName()));
  }

  @Override public SourceVersion getSupportedSourceVersion() {
    return SourceVersion.RELEASE_6;
  }

  public static void main(String[] args) {
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    List<String> classes = Arrays.asList(Y.class.getCanonicalName());
    List<String> options = Arrays.asList("-processor", MyProcessor.class
        .getCanonicalName());
    CompilationTask task = compiler.getTask(null, null, null, options, classes,
        null);
    task.call();
  }
}

The above code prints out "Hello".

McDowell
Why would you ever want to run annotation processors on class files? I thought the entire point of JavaCompiler was to compile source code, not class files. It's my understanding that annotation processors expand annotations in that source code that gets compiled in on-the-fly as if it was part of the original source code. Please clarify.
Gili
You can generate and compile classes as part of the processing. It is not always desirable to recompile everything all the time - if a full build takes an hour, for example. Or perhaps a container generates vendor-specific code when you install a binary plugin - the APT would be one way to do this (things like EJB containers). Note that the API mirrors the command line pretty closely: http://java.sun.com/javase/6/docs/technotes/tools/solaris/javac.html#synopsis If you want definitive answers, you may need to ask the JSR199 spec leads.
McDowell
So if I understand you correctly, compiling source-code runs through two phases: "source to binary" and "annotation processing". Are you saying that parameter lets you skip the "source to binary" phase and only do "annotation processing"?
Gili
Essentially, though it could be "annotation processing", "generate new source" (see Filer interface), "source to binary", repeat until no more code is generated. The number of rounds that are run is not fixed. You could have multiple processors feeding each other annotated input.
McDowell
A: 

I'm afraid I still don't understand. Why not just set a class path in the options?

Myshkin
My guess is that the annotation processor uses a separate classpath than what is used to find classes related to the compilation process.
Gili