{"id":43732,"date":"2015-09-18T21:53:20","date_gmt":"2015-09-18T18:53:20","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=43732"},"modified":"2023-12-06T14:23:51","modified_gmt":"2023-12-06T12:23:51","slug":"java-compiler-api","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html","title":{"rendered":"Java Compiler API"},"content":{"rendered":"<p><em>This article is part of our Academy Course titled <a href=\"http:\/\/www.javacodegeeks.com\/2015\/09\/advanced-java.html\">Advanced Java<\/a>.<\/p>\n<p>This course is designed to help you make the most effective use of Java. It discusses advanced topics, including object creation, concurrency, serialization, reflection and many more. It will guide you through your journey to Java mastery! Check it out <a href=\"http:\/\/www.javacodegeeks.com\/2015\/09\/advanced-java.html\">here<\/a>!<\/em><\/p>\n<div class=\"toc\">\n<h4>Table Of Contents<\/h4>\n<dl>\n<dt><a href=\"#introduction\">1. Introduction<\/a><\/dt>\n<dt><a href=\"#two\">2. Java Compiler API<\/a><\/dt>\n<dt><a href=\"#three\">3. Annotation Processors<\/a><\/dt>\n<dt><a href=\"#four\">4. Element Scanners<\/a><\/dt>\n<dt><a href=\"#five\">5. Java Compiler Tree API<\/a><\/dt>\n<dt><a href=\"#six\">6. What\u2019s next<\/a><\/dt>\n<dt><a href=\"#download\">7. Download<\/a><\/dt>\n<\/dl>\n<\/div>\n<h2><a name=\"introduction\"><\/a>1. Introduction<\/h2>\n<p>In this part of the tutorial we are going to take 10000 feet view of the Java Compiler API. This API provides programmatic access to the Java compiler itself and allows developers to compile Java classes from source files on the fly from application code.<\/p>\n<p>More interestingly, we also are going to walk through the Java Compiler Tree API, which provides access to Java syntax parser functionality. By using this API, Java developers have the ability to directly plug into syntax parsing phase and post-analyze Java source code being compiled. It is a very powerful API which is heavily utilized by many static code analysis tools.<\/p>\n<p>The Java Compiler API also supports annotation processing (for more details please refer to <strong>part 5<\/strong> of the tutorial, <strong>How and when to use Enums and Annotations<\/strong>, more to come in <strong>part 14<\/strong> of the tutorial, <strong>Annotation Processors<\/strong>) and is split between three different packages, shown in the table below.<\/p>\n<table style=\"width:100%\">\n<tr>\n<th>Package<\/th>\n<th>Description<\/th>\n<\/tr>\n<tr>\n<td><strong>javax.annotation.processing<\/strong><\/td>\n<td>Annotation processing.<\/td>\n<\/tr>\n<tr>\n<td><strong>javax.lang.model<\/strong><\/td>\n<td>Language model used in annotation processing and Compiler Tree API (including Java language elements, types and utility classes).<\/td>\n<\/tr>\n<tr>\n<td><strong>javax.tools<\/strong><\/td>\n<td>Java Compiler API itself.<\/td>\n<\/tr>\n<\/table>\n<p>&nbsp;<br \/>\nOn the other side, the Java Compiler Tree API is hosted under the <code>com.sun.source package<\/code> and, following Java standard library naming conventions, is considered to be non-standard (proprietary or internal). In general, these APIs are not very well documented or supported and could change any time. Moreover, they are tied to the particular JDK\/JRE version and may limit the portability of the applications which use them.<\/p>\n<h2><a name=\"two\"><\/a>2. Java Compiler API<\/h2>\n<p>Our exploration will start from the Java Compiler API, which is quite well documented and easy to use. The entry point into Java Compiler API is the <a href=\"http:\/\/docs.oracle.com\/javase\/7\/docs\/api\/javax\/tools\/ToolProvider.html\" target=\"_blank\" rel=\"noopener\">ToolProvider class<\/a>, which allows to obtain the Java compiler instance available in the system (the <a href=\"http:\/\/docs.oracle.com\/javase\/7\/docs\/api\/javax\/tools\/JavaCompiler.html\" target=\"_blank\" rel=\"noopener\">official documentation<\/a> is a great starting point to get familiarized with the typical usage scenarios). For example: <\/p>\n<pre class=\"brush:java\">final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();        \nfor( final SourceVersion version: compiler.getSourceVersions() ) {\n    System.out.println( version );\n}\n<\/pre>\n<p>This small code snippet gets the Java compiler instances and prints out on the console a list of supported Java source versions. For <strong>Java 7<\/strong> compiler, the output looks like this:<\/p>\n<pre class=\"brush:bash\">\nRELEASE_3\nRELEASE_4\nRELEASE_5\nRELEASE_6\nRELEASE_7\n<\/pre>\n<p>It corresponds to more well-known Java version scheme: <strong>1.3<\/strong>, <strong>1.4<\/strong>, <strong>5<\/strong>, <strong>6<\/strong> and <strong>7<\/strong>. For <strong>Java 8<\/strong> compiler, the list of supported versions looks a bit longer:<\/p>\n<pre class=\"brush:bash\">\nRELEASE_3\nRELEASE_4\nRELEASE_5\nRELEASE_6\nRELEASE_7\nRELEASE_8\n<\/pre>\n<p>Once the instance of Java compiler is available, it could be used to perform different compilation tasks over the set of Java source files. But before that, the set of compilation units and diagnostics collector (to collect all encountered compilation errors) should be prepared. To experiment with, we are going to compile this simple Java class stored in <code>SampleClass.java<\/code> source file:<\/p>\n<pre class=\"brush:java\">\npublic class SampleClass {\n    public static void main(String[] args) {\n        System.out.println( \"SampleClass has been compiled!\" );\n    }\n}\n<\/pre>\n<p>Having this source file created, let us instantiate the <a href=\"http:\/\/docs.oracle.com\/javase\/7\/docs\/api\/javax\/tools\/DiagnosticCollector.html\" target=\"_blank\" rel=\"noopener\">diagnostics collector<\/a> and configure the list of source files (which includes only <code>SampleClass.java<\/code>) to compile.<\/p>\n<pre class=\"brush:java\">\nfinal DiagnosticCollector&lt; JavaFileObject &gt; diagnostics = new DiagnosticCollector&lt;&gt;();\nfinal StandardJavaFileManager manager = compiler.getStandardFileManager( \n    diagnostics, null, null );\n        \nfinal File file = new File( \n    CompilerExample.class.getResource(\"\/SampleClass.java\").toURI() );\n\nfinal Iterable&lt; ? extends JavaFileObject &gt; sources = \n    manager.getJavaFileObjectsFromFiles( Arrays.asList( file ) );     \n<\/pre>\n<p>Once the preparation is done, the last step is basically to invoke Java compiler task, passing the diagnostics collector and list of source files to it, for example:<\/p>\n<pre class=\"brush:java\">\nfinal CompilationTask task = compiler.getTask( null, manager, diagnostics, \n    null, null, sources );            \ntask.call();\n<\/pre>\n<p>That is, basically, it. After the compilation task finishes, the <code>SampleClass.class<\/code> should be available in the <strong>target\/classes<\/strong> folder. We can run it to make sure compilation has been performed successfully: <\/p>\n<pre class=\"brush:bash\">java -cp target\/classes SampleClass<\/pre>\n<p>The following output will be shown on the console, confirming that the source file has been properly compiled into byte code:<\/p>\n<pre class=\"brush:bash\">SampleClass has been compiled!<\/pre>\n<p>In case of any errors encountered during the compilation process, they will become available through the diagnostics collector (by default, any additional compiler output will be printed into <code>System.err<\/code> too). To illustrate that, let us try to compile the sample Java source file which by intention contains some errors (<code>SampleClassWithErrors.java<\/code>):<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\"brush:java\">private class SampleClassWithErrors {\n    public static void main(String[] args) {\n        System.out.println( \"SampleClass has been compiled!\" );\n    }\n}<\/pre>\n<p>The compilation process should fail and error message (including line number and source file name) could be retrieved from diagnostics collector, for example:<\/p>\n<pre class=\"brush:java\">\nfor( final Diagnostic&lt; ? extends JavaFileObject &gt; diagnostic: \n            diagnostics.getDiagnostics() ) {\n            \n        System.out.format(\"%s, line %d in %s\", \n            diagnostic.getMessage( null ),\n            diagnostic.getLineNumber(),\n            diagnostic.getSource().getName() );\n}\n<\/pre>\n<p>Invoking the compilation task on the <code>SampleClassWithErrors.java<\/code> source file will print out on the console the following sample error description:<\/p>\n<pre class=\"brush:bash\">modifier private not allowed here, line 1 in SampleClassWithErrors.java\n<\/pre>\n<p>Last but not least, to properly finish up working with the Java Compiler API, please do not forget to close file manager:<\/p>\n<pre class=\"brush:java\">\nmanager.close();\n<\/pre>\n<p>Or even better, always use <code>try-with-resources<\/code> construct (which has been covered in <strong>part 8<\/strong> of the tutorial, <strong>How and when to use Exceptions<\/strong>):<\/p>\n<pre class=\"brush:java\">\ntry( final StandardJavaFileManager manager = \n        compiler.getStandardFileManager( diagnostics, null, null ) ) {\n    \/\/ Implementation here            \n} \n<\/pre>\n<p>In a nutshell, those are typical usage scenarios of Java Compiler API. When dealing with more complicated examples, there is a couple of subtle but quite important details which could speed up the compilation process significantly. To read more about that please refer to the <a href=\"http:\/\/docs.oracle.com\/javase\/7\/docs\/api\/javax\/tools\/JavaCompiler.html\" target=\"_blank\" rel=\"noopener\">official documentation<\/a>.<\/p>\n<h2><a name=\"three\"><\/a>3. Annotation Processors<\/h2>\n<p>Fortunately, the compilation process is not limited to compilation only. Java Compiler supports annotation processors which could be thought as a compiler plugins. As the name suggests, annotation processors could perform addition processing (usually driven by annotations) over the code being compiled.<\/p>\n<p>In the <strong>part 14<\/strong> of the tutorial, <strong>Annotation Processors<\/strong>, we are going to have much more comprehensive coverage and examples of annotation processors. For the moment, please refer to <a href=\"http:\/\/docs.oracle.com\/javase\/7\/docs\/api\/javax\/annotation\/processing\/package-summary.html\" target=\"_blank\" rel=\"noopener\">official documentation<\/a> to get more details.<\/p>\n<h2><a name=\"four\"><\/a>4. Element Scanners<\/h2>\n<p>Sometimes it becomes necessary to perform shallow analysis across all language elements (classes, methods\/constructors, fields, parameters, variables, \u2026) during the compilation process. Specifically for that, the Java Compiler API provides the concept of element scanners. The element scanners are built around <a href=\"http:\/\/en.wikipedia.org\/wiki\/Visitor_pattern\" target=\"_blank\" rel=\"noopener\">visitor pattern<\/a> and basically require the implementation of the single scanner (and visitor). To simplify the implementation, a set of base classes is kindly provided. <\/p>\n<p>The example we are going to develop is simple enough to show off the basic concepts of element scanners usage and is going to count all classes, methods and fields across all compilation units. The basic scanner \/ visitor implementation extends <a href=\"https:\/\/docs.oracle.com\/javase\/7\/docs\/api\/javax\/lang\/model\/util\/ElementScanner7.html\" target=\"_blank\" rel=\"noopener\">ElementScanner7<\/a> class and overrides only the methods it is interested in:<\/p>\n<pre class=\"brush:java\">\npublic class CountClassesMethodsFieldsScanner extends ElementScanner7&lt; Void, Void &gt; {\n    private int numberOfClasses;\n    private int numberOfMethods;\n    private int numberOfFields;\n    \n    public Void visitType( final TypeElement type, final Void p ) {\n        ++numberOfClasses;\n        return super.visitType( type, p );\n    }\n\n    public Void visitExecutable( final ExecutableElement executable, final Void p ) {\n        ++numberOfMethods;\n        return super.visitExecutable( executable, p );\n    }\n\n    public Void visitVariable( final VariableElement variable, final Void p ) {\n        if ( variable.getEnclosingElement().getKind() == ElementKind.CLASS ) {\n            ++numberOfFields;\n        }\n        \n        return super.visitVariable( variable, p );\n    }\n}\n<\/pre>\n<p>Quick note on the element scanners: the family of <strong>ElementScannerX<\/strong> classes corresponds to the particular Java version. For instance, <a href=\"http:\/\/docs.oracle.com\/javase\/8\/docs\/api\/javax\/lang\/model\/util\/ElementScanner8.html\" target=\"_blank\" rel=\"noopener\">ElementScanner8<\/a> corresponds to <strong>Java 8<\/strong>,  <a href=\"http:\/\/docs.oracle.com\/javase\/7\/docs\/api\/javax\/lang\/model\/util\/ElementScanner7.html\" target=\"_blank\" rel=\"noopener\">ElementScanner7<\/a> corresponds to <strong>Java 7<\/strong>,  <a href=\"http:\/\/docs.oracle.com\/javase\/6\/docs\/api\/javax\/lang\/model\/util\/ElementScanner6.html\" target=\"_blank\" rel=\"noopener\">ElementScanner6<\/a> corresponds to <strong>Java 6<\/strong>,  and so forth. All those classes do have a family of <code>visitXxx<\/code> methods which include:<\/p>\n<table style=\"width:100%\">\n<tr>\n<th>Method<\/th>\n<th>\tDescription<\/th>\n<\/tr>\n<tr>\n<td><strong>visitPackage<\/strong>\t<\/td>\n<td>Visits a package element.<\/td>\n<\/tr>\n<tr>\n<td><strong>visitType<\/strong>\t<\/td>\n<td>Visits a type element.<\/td>\n<\/tr>\n<tr>\n<td><strong>visitVariable<\/strong>\t<\/td>\n<td>Visits a variable element.<\/td>\n<\/tr>\n<tr>\n<td><strong>visitExecutable<\/strong>\t<\/td>\n<td>Visits an executable element.<\/td>\n<\/tr>\n<tr>\n<td><strong>visitTypeParameter<\/strong>\t<\/td>\n<td>Visits a type parameter element.<\/td>\n<\/tr>\n<\/table>\n<p>&nbsp;<\/p>\n<p>One of the ways to invoke the scanner (and visitors) during the compilation process is by using the annotation processor. Let us define one by extending <a href=\"http:\/\/docs.oracle.com\/javase\/7\/docs\/api\/javax\/annotation\/processing\/AbstractProcessor.html\" target=\"_blank\" rel=\"noopener\">AbstractProcessor<\/a> class (please notice that annotation processors are also tight to particular Java version, in our case <strong>Java 7<\/strong>):<\/p>\n<pre class=\"brush:java\">\n@SupportedSourceVersion( SourceVersion.RELEASE_7 )\n@SupportedAnnotationTypes( \"*\" )\npublic class CountElementsProcessor extends AbstractProcessor {\n    private final CountClassesMethodsFieldsScanner scanner;\n    \n    public CountElementsProcessor( final CountClassesMethodsFieldsScanner scanner ) {\n        this.scanner = scanner;\n    }\n    \n    public boolean process( final Set&lt; ? extends TypeElement &gt; types, \n            final RoundEnvironment environment ) {\n\n        if( !environment.processingOver() ) {\n            for( final Element element: environment.getRootElements() ) {\n                scanner.scan( element );\n            }\n        }\n        \n        return true;\n    }\n}\n<\/pre>\n<p>Basically, the annotation processor just delegates all the hard work to the scanner implementation we have defined before (in the <strong>part 14<\/strong> of the tutorial, <strong>Annotation Processors<\/strong>, we are going to have much more comprehensive coverage and examples of annotation processors).<\/p>\n<p>The <code>SampleClassToParse.java<\/code> file is the example which we are going to compile and count all classes, methods\/constructors and fields in:<\/p>\n<pre class=\"brush:java\">\npublic class SampleClassToParse {\n    private String str;\n    \n    private static class InnerClass {     \n        private int number;\n        \n        public void method() {\n            int i = 0;\n            \n            try {\n                \/\/ Some implementation here\n            } catch( final Throwable ex ) {\n                \/\/ Some implementation here\n            }\n        }\n    }\n    \n    public static void main( String[] args ) {\n        System.out.println( \"SampleClassToParse has been compiled!\" );\n    }\n}\n<\/pre>\n<p>The compilation procedure looks exactly like we have seen in the <a href=\"#two\">Java Compiler API<\/a> section. The only difference is that compilation task should be configured with annotation processor instance(s). To illustrate that, let us take a look on the code snippet below:<\/p>\n<pre class=\"brush:java\">\nfinal CountClassesMethodsFieldsScanner scanner = new CountClassesMethodsFieldsScanner();\nfinal CountElementsProcessor processor = new CountElementsProcessor( scanner );\n\nfinal CompilationTask task = compiler.getTask( null, manager, diagnostics, \n    null, null, sources );\ntask.setProcessors( Arrays.asList( processor ) );\ntask.call();\n\nSystem.out.format( \"Classes %d, methods\/constructors %d, fields %d\",\n    scanner.getNumberOfClasses(),\n    scanner.getNumberOfMethods(), \n    scanner.getNumberOfFields() );\n<\/pre>\n<p>Executing the compilation task against <code>SampleClassToParse.java<\/code> source file will output the following message in the console:<\/p>\n<pre class=\"brush:bash\">Classes 2, methods\/constructors 4, fields 2<\/pre>\n<p>It makes sense: there are two classes declared, <code>SampleClassToParse<\/code> and <code>InnerClass<\/code>. <code>SampleClassToParse<\/code> class has <code>default constructor<\/code> (defined implicitly), method <code>main<\/code> and field <code>str<\/code>. In turn, <code>InnerClass<\/code> class also has <code>default constructor<\/code> (defined implicitly), method <code>method<\/code> and field <code>number<\/code>.<\/p>\n<p>This example is very naive but its goal is not to demonstrate something fancy but rather to introduce the foundational concepts (the <strong>part 14<\/strong> of the tutorial, <strong>Annotation Processors<\/strong>, will include more complete examples).<br \/>\n[ulp id=&#8217;w6F4W4SAMiyTapBF&#8217;]<br \/>\n&nbsp;<\/p>\n<h2><a name=\"five\"><\/a>5. Java Compiler Tree API<\/h2>\n<p>Element scanners are quite useful but the details they provide access to are quite limited. Once in a while it becomes necessary to parse Java source files into abstract syntax trees (or <a href=\"http:\/\/en.wikipedia.org\/wiki\/Abstract_syntax_tree\" target=\"_blank\" rel=\"noopener\">AST<\/a>) and perform more deep analysis. Java Compiler Tree API is the tool we need to make it happen. Java Compiler Tree API works closely with Java Compiler API and uses <code>javax.lang.model<\/code> package. <\/p>\n<p>The usage of Java Compiler Tree API is very similar to the element scanners from section <a href=\"#four\">Element Scanners<\/a> and is built following the same patterns. Let us reuse the sample source file <code>SampleClassToParse.java<\/code> from <a href=\"#four\">Element Scanners<\/a> section and count how many empty <code>try\/catch<\/code> blocks are present across all compilation units. To do that, we have to define tree path scanner (and visitor), similarly to element scanner (and visitor) by extending <a href=\"http:\/\/docs.oracle.com\/javase\/7\/docs\/jdk\/api\/javac\/tree\/com\/sun\/source\/util\/TreePathScanner.html\" target=\"_blank\" rel=\"noopener\">TreePathScanner<\/a> base class.<\/p>\n<pre class=\"brush:java\">public class EmptyTryBlockScanner extends TreePathScanner&lt; Object, Trees &gt; {\n    private int numberOfEmptyTryBlocks;\n    \n    @Override\n    public Object visitTry(final TryTree tree, Trees trees) {\n        if( tree.getBlock().getStatements().isEmpty() ){\n            ++numberOfEmptyTryBlocks;\n        }\n        \n        return super.visitTry( tree, trees );\n    }\n    \n    public int getNumberOfEmptyTryBlocks() {\n        return numberOfEmptyTryBlocks;\n    }\n}<\/pre>\n<p>The number of <code>visitXxx<\/code> methods is significantly richer (around 50 methods) comparing to element scanners and covers all Java language syntax constructs. As with element scanners, one of the ways to invoke tree path scanners is also by defining dedicate annotation processor, for example:<\/p>\n<pre class=\"brush:java\">@SupportedSourceVersion( SourceVersion.RELEASE_7 )\n@SupportedAnnotationTypes( \"*\" )\npublic class EmptyTryBlockProcessor extends AbstractProcessor {\n    private final EmptyTryBlockScanner scanner;\n    private Trees trees;\n    \n    public EmptyTryBlockProcessor( final EmptyTryBlockScanner scanner ) {\n        this.scanner = scanner;\n    }\n    \n    @Override\n    public synchronized void init( final ProcessingEnvironment processingEnvironment ) {\n        super.init( processingEnvironment );\n        trees = Trees.instance( processingEnvironment );\n    }\n    \n    public boolean process( final Set&lt; ? extends TypeElement &gt; types, \n            final RoundEnvironment environment ) {\n\n        if( !environment.processingOver() ) {\n            for( final Element element: environment.getRootElements() ) {\n                scanner.scan( trees.getPath( element ), trees );\n            }\n        }\n        \n        return true;\n    }\n}<\/pre>\n<p>The initialization procedure became a little bit more complex as we have to obtain the instance of Trees class and convert each element into tree path representation. At this moment, the compilation steps should look very familiar and be clear enough. To make it a little bit more interesting, let us run it against all source files we have experimenting with so far: <code>SampleClassToParse.java<\/code> and <code>SampleClass.java<\/code>.<\/p>\n<pre class=\"brush:java\">final EmptyTryBlockScanner scanner = new EmptyTryBlockScanner();\nfinal EmptyTryBlockProcessor processor = new EmptyTryBlockProcessor( scanner );\n\nfinal Iterable&lt;? extends JavaFileObject&gt; sources = manager.getJavaFileObjectsFromFiles( \n    Arrays.asList( \n        new File(CompilerExample.class.getResource(\"\/SampleClassToParse.java\").toURI()),\n        new File(CompilerExample.class.getResource(\"\/SampleClass.java\").toURI())\n    ) \n);\n\nfinal CompilationTask task = compiler.getTask( null, manager, diagnostics, \n    null, null, sources );\ntask.setProcessors( Arrays.asList( processor ) );\ntask.call();\n\nSystem.out.format( \"Empty try\/catch blocks: %d\", scanner.getNumberOfEmptyTryBlocks() ); <\/pre>\n<p>Once run against multiple source files, the code snippet above is going to print the following output in the console:<\/p>\n<pre class=\"brush:bash\">Empty try\/catch blocks: 1<\/pre>\n<p>The Java Compiler Tree API may look a little bit low-level and it certainly is. Plus, being an internal API, it does not have well-supported documentation available. However, it gives the full access to the abstract syntax trees and it is a life-saver when you need to perform deep source code analysis and post-processing.<\/p>\n<h2><a name=\"six\"><\/a>6. What\u2019s next<\/h2>\n<p>In this part of the tutorial we have looked at programmatic access to Java Compiler API from within the Java applications. We also dug deeper, touched annotation processors and uncovered Java Compiler Tree API which provides the full access to abstract syntax trees of the Java source files being compiled (compilation units). In the next part of the tutorial we are going to continue in the same vein and take a closer look on annotation processors and their applicability.<\/p>\n<h2><a name=\"download\"><\/a>7. Download<\/h2>\n<p>This was a lesson for the Java Compiler API, part 13 of Advanced Java Course. You can download the source code of the lesson here: <a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/09\/advanced-java-part-13.zip\"><strong>advanced-java-part-13<\/strong><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article is part of our Academy Course titled Advanced Java. This course is designed to help you make the most effective use of Java. It discusses advanced topics, including object creation, concurrency, serialization, reflection and many more. It will guide you through your journey to Java mastery! Check it out here! Table Of Contents &hellip;<\/p>\n","protected":false},"author":141,"featured_media":148,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[343,88,580,557,65],"class_list":["post-43732","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-core-java","tag-annotations","tag-concurrency","tag-generics","tag-reflection","tag-serialization"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Java Compiler API - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"This article is part of our Academy Course titled Advanced Java. This course is designed to help you make the most effective use of Java. It discusses\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Java Compiler API - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"This article is part of our Academy Course titled Advanced Java. This course is designed to help you make the most effective use of Java. It discusses\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2015-09-18T18:53:20+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-12-06T12:23:51+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Andrey Redko\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andrey Redko\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-compiler-api.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-compiler-api.html\"},\"author\":{\"name\":\"Andrey Redko\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/771a6504862edc45322776832cbce413\"},\"headline\":\"Java Compiler API\",\"datePublished\":\"2015-09-18T18:53:20+00:00\",\"dateModified\":\"2023-12-06T12:23:51+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-compiler-api.html\"},\"wordCount\":1709,\"commentCount\":11,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-compiler-api.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"keywords\":[\"Annotations\",\"Concurrency\",\"Generics\",\"Reflection\",\"Serialization\"],\"articleSection\":[\"Core Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-compiler-api.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-compiler-api.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-compiler-api.html\",\"name\":\"Java Compiler API - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-compiler-api.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-compiler-api.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"datePublished\":\"2015-09-18T18:53:20+00:00\",\"dateModified\":\"2023-12-06T12:23:51+00:00\",\"description\":\"This article is part of our Academy Course titled Advanced Java. This course is designed to help you make the most effective use of Java. It discusses\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-compiler-api.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-compiler-api.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-compiler-api.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-compiler-api.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Core Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/core-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Java Compiler API\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/771a6504862edc45322776832cbce413\",\"name\":\"Andrey Redko\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"caption\":\"Andrey Redko\"},\"description\":\"Andriy is a well-grounded software developer with more then 12 years of practical experience using Java\\\/EE, C#\\\/.NET, C++, Groovy, Ruby, functional programming (Scala), databases (MySQL, PostgreSQL, Oracle) and NoSQL solutions (MongoDB, Redis).\",\"sameAs\":[\"http:\\\/\\\/aredko.blogspot.com\\\/\",\"http:\\\/\\\/ca.linkedin.com\\\/in\\\/aredko\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/andrey-redko\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Java Compiler API - Java Code Geeks","description":"This article is part of our Academy Course titled Advanced Java. This course is designed to help you make the most effective use of Java. It discusses","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html","og_locale":"en_US","og_type":"article","og_title":"Java Compiler API - Java Code Geeks","og_description":"This article is part of our Academy Course titled Advanced Java. This course is designed to help you make the most effective use of Java. It discusses","og_url":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2015-09-18T18:53:20+00:00","article_modified_time":"2023-12-06T12:23:51+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","type":"image\/jpeg"}],"author":"Andrey Redko","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Andrey Redko","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html"},"author":{"name":"Andrey Redko","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/771a6504862edc45322776832cbce413"},"headline":"Java Compiler API","datePublished":"2015-09-18T18:53:20+00:00","dateModified":"2023-12-06T12:23:51+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html"},"wordCount":1709,"commentCount":11,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","keywords":["Annotations","Concurrency","Generics","Reflection","Serialization"],"articleSection":["Core Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html","url":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html","name":"Java Compiler API - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","datePublished":"2015-09-18T18:53:20+00:00","dateModified":"2023-12-06T12:23:51+00:00","description":"This article is part of our Academy Course titled Advanced Java. This course is designed to help you make the most effective use of Java. It discusses","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-compiler-api.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Core Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/core-java"},{"@type":"ListItem","position":4,"name":"Java Compiler API"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/771a6504862edc45322776832cbce413","name":"Andrey Redko","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","caption":"Andrey Redko"},"description":"Andriy is a well-grounded software developer with more then 12 years of practical experience using Java\/EE, C#\/.NET, C++, Groovy, Ruby, functional programming (Scala), databases (MySQL, PostgreSQL, Oracle) and NoSQL solutions (MongoDB, Redis).","sameAs":["http:\/\/aredko.blogspot.com\/","http:\/\/ca.linkedin.com\/in\/aredko"],"url":"https:\/\/www.javacodegeeks.com\/author\/andrey-redko"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/43732","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/141"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=43732"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/43732\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/148"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=43732"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=43732"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=43732"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}