public interface Compiler
{
String ROLE = Compiler.class.getName();
CompilerOutputStyle getCompilerOutputStyle();
String getInputFileEnding( CompilerConfiguration configuration )
throws CompilerException;
String getOutputFileEnding( CompilerConfiguration configuration )
throws CompilerException;
String getOutputFile( CompilerConfiguration configuration )
throws CompilerException;
boolean canUpdateTarget( CompilerConfiguration configuration )
throws CompilerException;
/**
* Performs the compilation of the project. Clients must implement this
* method.
*
* @param configuration the configuration description of the compilation
* to perform
* @return the result of the compilation returned by the language processor
* @throws CompilerException
*/
CompilerResult performCompile( CompilerConfiguration configuration )
throws CompilerException;
/**
* Create the command line that would be executed using this configuration.
* If this particular compiler has no concept of a command line then returns
* null.
*
* @param config the CompilerConfiguration describing the compilation
* @return an array of Strings that make up the command line, or null if
* this compiler has no concept of command line
* @throws CompilerException if there was an error generating the command
* line
*/
String[] createCommandLine( CompilerConfiguration config )
throws CompilerException;
/**
* Based on this flag the caller can decide the strategy how to compile. E.g. is incrementCompilation is not supported,
* it could decide to clear to outputDirectory to enforce a complete recompilation.
*
* @return {@code true} if incrementalCompilation is supported, otherwise {@code false}
*/
default boolean supportsIncrementalCompilation() {
return false;
}
}
与此同时在plexus-compiler-javac也有一个实现类JavacCompiler
/**
* @author <a href="mailto:trygvis@inamo.no">Trygve Laugstøl</a>
* @author <a href="mailto:matthew.pocock@ncl.ac.uk">Matthew Pocock</a>
* @author <a href="mailto:joerg.wassmer@web.de">Jörg Waßmer</a>
* @author Others
*
*/
@Component( role = Compiler.class, hint = "javac ")
public class JavacCompiler
extends AbstractCompiler {
@Override
public String getCompilerId() {
return "javac";
}
//开始执行编译
@Override
public CompilerResult performCompile( CompilerConfiguration config )
throws CompilerException {
File destinationDir = new File( config.getOutputLocation() );
if ( !destinationDir.exists() ) {
destinationDir.mkdirs();
}
//要编译的源文件
String[] sourceFiles = getSourceFiles(config );
if (( sourceFiles == null ) || ( sourceFiles.length == 0 )){
return new CompilerResult();
}
//构建编译所需的参数
String[] args = buildCompilerArguments( config, sourceFiles );
CompilerResult result;
if (config.isFork()) {
//从配置文件获取可执行文件
String executable = config.getExecutable();
if(StringUtils.isEmpty(executable )) {
try{
//获取执行Java编译的可执行文件
//获取javac工具可执行文件的路径:
//尝试根据操作系统或java.home系统属性
//或JAVA_HOME环境变量。
executable = getJavacExecutable();
}catch ( IOException e ){
if ( (getLogger() != null ) && getLogger().isWarnEnabled()) {
getLogger().warn( "Unable to autodetect 'javac' path, using 'javac' from the environment." );
}
//直接用javac命令
executable = "javac";
}
}
//在外部进程中编译java源代码,调用外部可执行文件,如javac。
result = compileOutOfProcess( config, executable, args );
} else {
if (isJava16() && !config.isForceJavacCompilerUse()){
// use fqcn to prevent loading of the class on 1.5 environment !
result =
inProcessCompiler().compileInProcess(args, config, sourceFiles );
} else {
//执行编译
//使用com.sun.tools.javac.Main类编译
//当前JVM中的java源代码,而不调用外部可执行文件
result = compileInProcess( args, config );
}
}
return result;
}
protected CompilerResult compileOutOfProcess( CompilerConfiguration config, String executable, String[] args )
throws CompilerException
{
Commandline cli = new Commandline();
cli.setWorkingDirectory( config.getWorkingDirectory()
.getAbsolutePath() );
//设置可执行文件
cli.setExecutable( executable );
// ... ...
}
Fatal error compiling: java.lang.ExceptionInInitializerError: Unable to make field private com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors com.sun.tools.javac.processing.JavacProcessingEnvironment.discoveredProcs accessible: module jdk.compiler does not "opens com.sun.tools.javac.processing" to unnamed module @388c519 -> [Help 1]
[ERROR] Failed to execute goal org.apache.maven.plugins:
maven-compiler-plugin:3.1:compile (default-compile)
on project xx-micro-basic: Fatal error compiling:
java.lang.IllegalAccessError: superclass access check failed:
class lombok.javac.apt.LombokFileObjects$Java9Compiler$FileManagerWrapper
(in unnamed module @0x68f6e55d) cannot access class com.sun.tools.javac.file.BaseFileManager (in module jdk.compiler)
because module jdk.compiler does not export com.sun.tools.javac.file to unnamed module @0x68f6e55d -> [Help 1]
说明:Java 16和Java 17封装了JDK内部api,这会影响各种框架,如Lombok。您可能会看到诸如module jdk.compiler does not export com.sun.tools.javac.processing to unnamed module的错误,这意味着您的应用程序不再能够访问JDK的那一部分。
public interface Compiler
{
String ROLE = Compiler.class.getName();
CompilerOutputStyle getCompilerOutputStyle();
String getInputFileEnding( CompilerConfiguration configuration )
throws CompilerException;
String getOutputFileEnding( CompilerConfiguration configuration )
throws CompilerException;
String getOutputFile( CompilerConfiguration configuration )
throws CompilerException;
boolean canUpdateTarget( CompilerConfiguration configuration )
throws CompilerException;
/**
* Performs the compilation of the project. Clients must implement this
* method.
*
* @param configuration the configuration description of the compilation
* to perform
* @return the result of the compilation returned by the language processor
* @throws CompilerException
*/
CompilerResult performCompile( CompilerConfiguration configuration )
throws CompilerException;
/**
* Create the command line that would be executed using this configuration.
* If this particular compiler has no concept of a command line then returns
* null.
*
* @param config the CompilerConfiguration describing the compilation
* @return an array of Strings that make up the command line, or null if
* this compiler has no concept of command line
* @throws CompilerException if there was an error generating the command
* line
*/
String[] createCommandLine( CompilerConfiguration config )
throws CompilerException;
/**
* Based on this flag the caller can decide the strategy how to compile. E.g. is incrementCompilation is not supported,
* it could decide to clear to outputDirectory to enforce a complete recompilation.
*
* @return {@code true} if incrementalCompilation is supported, otherwise {@code false}
*/
default boolean supportsIncrementalCompilation() {
return false;
}
}
与此同时在plexus-compiler-javac也有一个实现类JavacCompiler
/**
* @author <a href="mailto:trygvis@inamo.no">Trygve Laugstøl</a>
* @author <a href="mailto:matthew.pocock@ncl.ac.uk">Matthew Pocock</a>
* @author <a href="mailto:joerg.wassmer@web.de">Jörg Waßmer</a>
* @author Others
*
*/
@Component( role = Compiler.class, hint = "javac ")
public class JavacCompiler
extends AbstractCompiler {
@Override
public String getCompilerId() {
return "javac";
}
//开始执行编译
@Override
public CompilerResult performCompile( CompilerConfiguration config )
throws CompilerException {
File destinationDir = new File( config.getOutputLocation() );
if ( !destinationDir.exists() ) {
destinationDir.mkdirs();
}
//要编译的源文件
String[] sourceFiles = getSourceFiles(config );
if (( sourceFiles == null ) || ( sourceFiles.length == 0 )){
return new CompilerResult();
}
//构建编译所需的参数
String[] args = buildCompilerArguments( config, sourceFiles );
CompilerResult result;
if (config.isFork()) {
//从配置文件获取可执行文件
String executable = config.getExecutable();
if(StringUtils.isEmpty(executable )) {
try{
//获取执行Java编译的可执行文件
//获取javac工具可执行文件的路径:
//尝试根据操作系统或java.home系统属性
//或JAVA_HOME环境变量。
executable = getJavacExecutable();
}catch ( IOException e ){
if ( (getLogger() != null ) && getLogger().isWarnEnabled()) {
getLogger().warn( "Unable to autodetect 'javac' path, using 'javac' from the environment." );
}
//直接用javac命令
executable = "javac";
}
}
//在外部进程中编译java源代码,调用外部可执行文件,如javac。
result = compileOutOfProcess( config, executable, args );
} else {
if (isJava16() && !config.isForceJavacCompilerUse()){
// use fqcn to prevent loading of the class on 1.5 environment !
result =
inProcessCompiler().compileInProcess(args, config, sourceFiles );
} else {
//执行编译
//使用com.sun.tools.javac.Main类编译
//当前JVM中的java源代码,而不调用外部可执行文件
result = compileInProcess( args, config );
}
}
return result;
}
protected CompilerResult compileOutOfProcess( CompilerConfiguration config, String executable, String[] args )
throws CompilerException
{
Commandline cli = new Commandline();
cli.setWorkingDirectory( config.getWorkingDirectory()
.getAbsolutePath() );
//设置可执行文件
cli.setExecutable( executable );
// ... ...
}
Fatal error compiling: java.lang.ExceptionInInitializerError: Unable to make field private com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors com.sun.tools.javac.processing.JavacProcessingEnvironment.discoveredProcs accessible: module jdk.compiler does not "opens com.sun.tools.javac.processing" to unnamed module @388c519 -> [Help 1]
[ERROR] Failed to execute goal org.apache.maven.plugins:
maven-compiler-plugin:3.1:compile (default-compile)
on project xx-micro-basic: Fatal error compiling:
java.lang.IllegalAccessError: superclass access check failed:
class lombok.javac.apt.LombokFileObjects$Java9Compiler$FileManagerWrapper
(in unnamed module @0x68f6e55d) cannot access class com.sun.tools.javac.file.BaseFileManager (in module jdk.compiler)
because module jdk.compiler does not export com.sun.tools.javac.file to unnamed module @0x68f6e55d -> [Help 1]
说明:Java 16和Java 17封装了JDK内部api,这会影响各种框架,如Lombok。您可能会看到诸如module jdk.compiler does not export com.sun.tools.javac.processing to unnamed module的错误,这意味着您的应用程序不再能够访问JDK的那一部分。