Eclipse Java编译器(ecj)相对于标准的javac编译器有很多优势。它速度快,可以配置更多警告和错误,提高代码质量。编译器中最有趣的事情之一是添加了
编译器内部的null类型:通过使用@Nullable和@NotNull注释来注释您的代码,您可以强制Eclipse编译器在编译时检查空访问,而不是运行时。严格应用此方法可以教您编写更安全的代码(通过防止空值),并防止测试或生产期间的NPE异常。
在Maven中使用Eclipse编译器并不难,但网络上存在很多错误信息和过时信息,这会导致很多混淆。我希望这可以帮助澄清事情。
要使Maven使用ecj编译器,您需要使用plexus-compiler-eclipse插件,而不使用其他任何东西。典型的配置如下:
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<compilerId>eclipse</compilerId>
<source>${source.jdk.version}</source>
<target>${target.jdk.version}</target>
<compilerArguments>
<properties>${project.basedir}/.settings/org.eclipse.jdt.core.prefs</properties>
</compilerArguments>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-eclipse</artifactId>
<version>2.8.3</version>
</dependency>
<dependency>
<groupId>org.eclipse.jdt</groupId>
<artifactId>ecj</artifactId>
<version>3.13.101</version>
</dependency>
</dependencies>
</plugin>
</pluginManagement>
将此部分放在父/根pom的pluginManagement或build部分中。
现在让我们解释不同的部分;)
maven-compiler-plugin需要是最新版本。source和target参数定义要用于源代码和字节码的java版本,并且通常相同。
向编译器传递参数是一场灾难。请参见下面的单独部分。在此示例中,我使用了属性设置,允许我提供详细的设置,例如编译时我希望拥有哪些错误和警告。通过在参数内使用${project.basedir}变量,我可以为每个项目设置这些设置:每个项目都需要存在.settings/org.eclipse.jdt.core.prefs文件(这恰好是Eclipse IDE留下其编译器设置的位置)。
对plexus-codehaus-eclipse的依赖定义了知道如何运行Eclipse编译器的插件。2.8.3版本是撰写本文时的最新版本,但该版本存在一些问题。版本2.8.4应该会附带一个重写的编译器接口,修复了很多问题,但撰写本文时,该版本仍在进行中。您可以在此处找到有关该插件的详细信息,因此可以跟踪新发布/代码更改的进度。
另一个重要的依赖是org.eclipse.jdt:ecj依赖项:它指定了要使用的ecj编译器的确切版本。您应该始终指定它,否则在插件决定在您发布之前的某一天使用另一个版本的编译器时,构建稳定性将会受到影响;) ecj编译器要使用的版本号有点问题。您可以从
发布列表中找到版本号,然后检查
此Maven存储库是否有类似的内容。但是,这个存储库只包含旧版本。当您需要更近期的版本时,显然应该
在此处查看 - 这是Eclipse
当前推送其版本的地方。这个新的存储库放弃了早期存储库中易于识别的版本号;它使用像3.1x.x这样的版本号,如上所示。 Eclipse通常每年发布一个主要版本,以及一两个修复版本。 3.13.x号码中的第二部分对应于Eclipse平台项目内部版本控制用于发布的版本控制。很难获得列表,但至少这些是已知的:
Version Eclipse Release Compiler Version
3.13.0 Oxygen Release 4.7
3.13.50 Oxygen 1a 4.7.1a
3.13.100 Oxygen R2 4.7.2
版本号始终以3开头,13或多或少是发布的“年份”。因此,当13是氧气(2017年,4.7)时,14可能会是Photon(2018年,4.8)。
plexus-compiler-eclipse插件的版本:2.8.4之前
在2.8.4之前的版本中,plexus-compiler-plugin使用内部API启动Eclipse编译器。这导致许多功能不能正常工作,因为该内部API不解释ecj编译器的通常命令行参数。这使得它很难使用,并且一些功能不受支持。以下是限制列表:
注释处理未实现。任何配置都将被静默忽略。
通过使用<compilerArguments>标签添加特定参数很困难,因为实现存在多个问题:
编译器mojo似乎会向输入此处的所有参数添加破折号。然而,此插件版本使用的内部API需要没有破折号的参数。因此,插件会再次删除它们。
由于这里的参数不是真正的命令行ecj参数,因此很难知道要使用哪些参数:有关详细信息,请查看Eclipse源代码中的Compiler.java类和CompilerOptions.java类。
该插件确实接受一些参数,但这些参数由插件本身解释,然后“转换”为内部API。
此插件在<compilerArguments>标签中接受以下参数:
<properties>filename</properties>:定义一个属性文件,该文件将传递给编译器的-properties参数。可以通过查看Eclipse项目中的.settings/org.eclipse.jdt.core.prefs文件来找到此文件格式的示例:该文件存储编译器的配置。它包含警告、错误和信息消息以及编译器兼容性设置的设置。
<errorsAsWarnings>whatever</errorsAsWarnings>。当这个有效时,插件将忽略编译器生成的任何错误,并将它们报告为警告。当然,编译仍然失败,所以根据错误,可能已经写入/更新了.class文件或没有。这由插件本身处理:它只是将所有错误更改为警告,并告诉世界编译工作正常。
从2.8.4版本开始
plexus-compiler-eclipse插件的2.8.4版本已经被大部分重写。它现在使用ECJ编译器的公共API,这几乎就是ECJ编译器本身。例如,这意味着插件现在可以做ECJ能做的一切(如注释处理),并且输入在标签中的参数现在会传递给编译器,这意味着您应该能够使用ecj的帮助页面找到有趣的参数来添加。
与以前的版本一样,此版本还要求您从所有参数名称中删除“-”;在将参数名称添加到ecj命令行之前,破折号会自动添加回去。
这个版本支持 Maven 定义的注解处理;通过将所需部分添加到编译块中,您可以运行您的注解处理器。例如:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<annotationProcessors>
<annotationProcessor>db.annotationprocessing.EntityAnnotationProcessor</annotationProcessor>
</annotationProcessors>
<annotationProcessorPaths>
<dependency>
<groupId>to.etc.domui</groupId>
<artifactId>property-annotations-processor</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
</annotationProcessorPaths>
</configuration>
<dependencies>
<dependency>
<groupId>to.etc.domui</groupId>
<artifactId>property-annotations-processor</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
</dependencies>
</plugin>
这部分可能看起来不完整,因为根本没有提到plexus-compiler-eclipse插件,但请记住,在Maven中,该配置继承:在这种情况下,父POM包含上面的部分,而这只是为这个POM的项目添加了一些配置。