zoukankan      html  css  js  c++  java
  • No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?

    最近在MINGW64控制台中使用 maven 命令打包时出现如下错误。通常在 eclipse 或 IDEA这样的集成开发工具中,只要将工程的JDK环境变量重新设置一下,重新执行一下maven 打包命令即可。

     1 [INFO] ------------------------------------------------------------------------
     2 [INFO] BUILD FAILURE
     3 [INFO] ------------------------------------------------------------------------
     4 [INFO] Total time: 1.628 s
     5 [INFO] Finished at: 2018-08-21T12:05:46+08:00
     6 [INFO] ------------------------------------------------------------------------
     7 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile (default-compile) on project xxx-framework: Compilation failure
     8 [ERROR] No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
     9 [ERROR]
    10 [ERROR] -> [Help 1]
    11 org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile (default-compile) on project xxx-framework: Compilation failure
    12 No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
    13 
    14     at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:213)
    15     at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:154)
    16     at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:146)
    17     at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    18     at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    19     at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    20     at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    21     at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    22     at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    23     at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    24     at org.apache.maven.cli.MavenCli.execute (MavenCli.java:956)
    25     at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:290)
    26     at org.apache.maven.cli.MavenCli.main (MavenCli.java:194)
    27     at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    28     at sun.reflect.NativeMethodAccessorImpl.invoke (Unknown Source)
    29     at sun.reflect.DelegatingMethodAccessorImpl.invoke (Unknown Source)
    30     at java.lang.reflect.Method.invoke (Unknown Source)
    31     at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:289)
    32     at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:229)
    33     at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:415)
    34     at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:356)
    35 Caused by: org.apache.maven.plugin.compiler.CompilationFailureException: Compilation failure
    36 No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
    37 
    38     at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute (AbstractCompilerMojo.java:1161)
    39     at org.apache.maven.plugin.compiler.CompilerMojo.execute (CompilerMojo.java:168)
    40     at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    41     at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:208)
    42     at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:154)
    43     at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:146)
    44     at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    45     at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    46     at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    47     at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    48     at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    49     at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    50     at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    51     at org.apache.maven.cli.MavenCli.execute (MavenCli.java:956)
    52     at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:290)
    53     at org.apache.maven.cli.MavenCli.main (MavenCli.java:194)
    54     at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    55     at sun.reflect.NativeMethodAccessorImpl.invoke (Unknown Source)
    56     at sun.reflect.DelegatingMethodAccessorImpl.invoke (Unknown Source)
    57     at java.lang.reflect.Method.invoke (Unknown Source)
    58     at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:289)
    59     at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:229)
    60     at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:415)
    61     at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:356)
    62 [ERROR]
    63 [ERROR]
    64 [ERROR] For more information about the errors and possible solutions, please read the following articles:
    65 [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
    66 [ERROR]
    67 [ERROR] After correcting the problems, you can resume the build with the command
    [ERROR] mvn <goals> -rf :xxx-framework 

    错误源头分析:  

      我试了一下,在IDEA中是可以正常执行maven打包命令。由于这种错误出现过很多次,但是却不知道其背后的原因,这次又碰到了,于是决定从源头上看看究竟是什么原因导致的。根据上面的异常提示信息,一路追踪下来,发现异常是从这个类(如下所示,该类位于plexus-compiler-javac-2.8.2.jar 之中)的方法抛出来的。

    org.codehaus.plexus.compiler.javac.JavaxToolsCompiler.compileInProcess(String[], CompilerConfiguration, String[])

    很容易看出来是compiler等于null,导致出错。而compiler变量是由执行 getJavaCompiler 方法后赋值的。进入到这个方法(如下所示,该方法位于plexus-compiler-javac-2.8.2.jar 之中)里面去看看。

    org.codehaus.plexus.compiler.javac.JavaxToolsCompiler.getJavaCompiler(CompilerConfiguration)
     1     protected static JavaCompiler getJavaCompiler( CompilerConfiguration compilerConfiguration )
     2     {
     3         switch ( compilerConfiguration.getCompilerReuseStrategy() )
     4         {
     5             case AlwaysNew:
     6                 return ToolProvider.getSystemJavaCompiler();
     7             case ReuseCreated: //打断点跟踪会执行此处
     8                 JavaCompiler javaCompiler;
     9                 synchronized ( JAVA_COMPILERS )
    10                 {
    11                     if ( JAVA_COMPILERS.size() > 0 )
    12                     {
    13                         javaCompiler = JAVA_COMPILERS.get( 0 );
    14                         JAVA_COMPILERS.remove( javaCompiler );
    15                         return javaCompiler;
    16                     }
    17                 }
    18                 javaCompiler = ToolProvider.getSystemJavaCompiler();
    19                 return javaCompiler;
    20             case ReuseSame:
    21             default:
    22                 return COMPILER;
    23         }
    24 
    25     }
    打断点跟踪了一下,会执行 ReuseCreated 分支。JAVA_COMPILERS 列表大小为空,执行  ToolProvider.getSystemJavaCompiler(),进入到这个方法中,发现这个方法查找某接口的实现类(如下所示),然后加载该实现类并实例化。
    javax.tools.ToolProvider.getSystemJavaCompiler()

    private static final String defaultJavaCompilerName= "com.sun.tools.javac.api.JavacTool";

    跟踪到这儿,看到com.sun这个包我一时半会儿还没有反应过来,这个是JDK私有的包。既然了找不到实现类,那我就创建一个实现该接口的类,这样的话就不会报错了,然而当我把眼光停留到控制台那行红色错误提示信息上面,心想是不是应该使用 mvn -v 命令看一下,是不是加载的JDK路径不对导致的? 在 MINGW64 中执行 mvn -v 命令,控制台打印出来的信息如下所示:

    1 $ mvn -v
    2 Apache Maven 3.5.3 (3383c37e1f9e9b3bc3df5050c29c8aff9f295297; 2018-02-25T03:49:05+08:00)
    3 Maven home: D:progapache-maven-3.5.3
    4 Java version: 1.8.0_161, vendor: Oracle Corporation
    5 Java home: C:Program FilesJavajre
    6 Default locale: zh_CN, platform encoding: GBK
    7 OS name: "windows 7", version: "6.1", arch: "amd64", family: "windows"

    看到控制台输出的Java home路径,跟我在环境中配置的JAVA_HOME路径不一样,奇怪了? 打开cmd, 在cmd命令行中执行 mvn -v 命令,控制台打印出来的信息如下所示:

    1 C:Usershyt>mvn -v
    2 Apache Maven 3.5.3 (3383c37e1f9e9b3bc3df5050c29c8aff9f295297; 2018-02-25T03:49:05+08:00)
    3 Maven home: D:progapache-maven-3.5.3in..
    4 Java version: 1.8.0_161, vendor: Oracle Corporation
    5 Java home: C:Program FilesJavajdk1.8.0_161jre
    6 Default locale: zh_CN, platform encoding: GBK
    7 OS name: "windows 7", version: "6.1", arch: "amd64", family: "windows"

    对比之后,发现两者不一样,打开maven源码工程,看一下执行 mvn -v 命令的输出版本信息的方法,看一下究竟是从什么地方读取JDK的路径信息的。

    org.apache.maven.cli.MavenCli#version
    
        private void version( CliRequest cliRequest )
        {
            if ( cliRequest.debug || cliRequest.commandLine.hasOption( CLIManager.SHOW_VERSION ) )
            {
                System.out.println( CLIReportingUtils.showVersion() );
            }
        }
    org.apache.maven.cli.CLIReportingUtils#showVersion
    
        public static String showVersion()
        {
            final String ls = System.getProperty( "line.separator" );
            Properties properties = getBuildProperties();
            StringBuilder version = new StringBuilder( 256 );
            version.append( buffer().strong( createMavenVersionString( properties ) ) ).append( ls );
            version.append( reduce(
                properties.getProperty( "distributionShortName" ) + " home: " + System.getProperty( "maven.home",
                                                                                                    "<unknown Maven "
                                                                                                        + "home>" ) ) )
                .append( ls );
            version.append( "Java version: " ).append(
                System.getProperty( "java.version", "<unknown Java version>" ) ).append( ", vendor: " ).append(
                System.getProperty( "java.vendor", "<unknown vendor>" ) ).append( ", runtime: " ).append(
                System.getProperty( "java.home", "<unknown runtime>" ) ).append( ls );
            version.append( "Default locale: " ).append( Locale.getDefault() ).append( ", platform encoding: " ).append(
                System.getProperty( "file.encoding", "<unknown encoding>" ) ).append( ls );
            version.append( "OS name: "" ).append( Os.OS_NAME ).append( "", version: "" ).append( Os.OS_VERSION ).append(
                "", arch: "" ).append( Os.OS_ARCH ).append( "", family: "" ).append( Os.OS_FAMILY ).append( '"' );
            return version.toString();
        }

      看到这儿我明白了,是在执行mvn命令的时候传入JDK路径不正确,我手动传入JDK路径来试试看能不能解决这个问题。我找到mvn.cmd文件,在该文件中(如下所示位置,使用notepad++编辑打开)设置JAVA_HOME路径,在 MINGW64 中执行 mvn install 依然提示错误信息,mvn -v 打印出的信息中 java home 路径依然是错误的。mvn -DJAVA_HOME=C:/Program Files/Java/jdk1.8.0_161/ install  采用这样的方式强制传入JAVA_HOME参数,导致maven根本无法识别 install 命令。 

      看来得研究一下 MINGW64 和 cmd 这两者为什么打印出来的JDK路径不一样,难不成 MINGW64 没有读取系统环境变量。 不过在此之前我要先尝试一下在 maven-compile-plugin 插件中增加<forceJavacCompilerUse>true</forceJavacCompilerUse> 配置项。因为前面代码提示 compiler 为空,是因为使用了JavaxToolsCompiler来编译源代码,我让maven直接使用javac命令来编译源代码,这样就不会提示找不到complier,从而compiler为null,这样做因该不会出错。

    org.codehaus.plexus.compiler.javac.JavacCompiler.performCompile(CompilerConfiguration)

     //省略方法
    if ( isJava16() && !config.isForceJavacCompilerUse() ) { // use fqcn to prevent loading of the class on 1.5 environment ! result =org.codehaus.plexus.compiler.javac.JavaxToolsCompiler.compileInProcess( args, config, sourceFiles ); } else { result = compileInProcess( args, config ); }

    在工程的 pom.xml 文件中为 maven-compile-plugin 插件中增加 <forceJavacCompilerUse>true</forceJavacCompilerUse> 配置项。

     1             <plugin>
     2                 <groupId>org.apache.maven.plugins</groupId>
     3                 <artifactId>maven-compiler-plugin</artifactId>
     4                 <!-- since 2.0 -->
     5                 <version>3.7.0</version>
     6                 <configuration>
     7                     <!-- use the Java 8 language features -->
     8                     <source>1.8</source>
     9                     <!-- want the compiled classes to be compatible with JVM 1.8 -->
    10                     <target>1.8</target>
    11                     <!-- The -encoding argument for the Java compiler. -->
    12                     <encoding>UTF8</encoding>
    13                     <forceJavacCompilerUse>true</forceJavacCompilerUse>
    14                 </configuration>
    15             </plugin>

    在 MINGW64 中执行 mvn install 命令,错误依旧

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile (default-compile) on project xxx-framework: Fatal error compiling: tools.jar not found: C:Program FilesJavajre..lib	ools.jar -> [Help 1]
    [ERROR]
    [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
    [ERROR] Re-run Maven using the -X switch to enable full debug logging.
    [ERROR]
    [ERROR] For more information about the errors and possible solutions, please read the following articles:
    [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

      没办法,回到设置 MINGW64 读取windows环境变量的路子上来,只有这样才能读取正确的JDK路径。可是在网上找了好长时间,都是说如何设置 MINGW64 的C++  gcc环境变量之类,不是自己想要。猛然脑海中想到3个字“注册表”。果然在“注册表”中找到与JDK相关的配置项。

    HKEY_LOCAL_MACHINESOFTWAREJavaSoftJava Runtime Environment


    问题的解决办法:

    编辑注册表中相关的配置项,来解决这个问题。配置如下所示:

    使用上面的配置之后,在 MINGW64 中执行 mvn install 命令之后,控制台提示报错。

    $ mvn install
    Error: could not open `C:Program FilesJavajdk1.8.0_161libamd64jvm.cfg'

    我在这个目录下面去看了一下,果然没有这个文件。在这个路径 C:Program FilesJavajdk1.8.0_161jrelibamd64 才有相关的配置,修改一下配置,如下所示:

     

     在 MINGW64 中执行mvn  install命令,控制台提示打包成功,mvn -v 输出的信息显示jdk路径也配置正确。


    原因分析:

    对 C:Program FilesJavajre 和 C:Program FilesJavajdk1.8.0_161jre 这二者之间的区别没有弄清楚。开发的时候要指向JDK中的jre,因为要根据该jre的位置来做定位,加载JDK中的相关资源。比如上面maven要加载JDK中的com.sun私有包。关于这二者的区别可以在网上搜索,有关这方面的文章挺多的。 

     附CSDN上的某篇文章: java中的两个jre区别 https://blog.csdn.net/sanjiaozhen/article/details/45157565

  • 相关阅读:
    动态页面技术(JSP/EL/JSTL)
    JavaWeb核心之Servlet
    会话技术Cookie&Session
    待整理
    二进制中1的个数(python)
    矩形覆盖(python)
    变态跳台阶(python)
    跳台阶(python)
    斐波那契数列(python)
    旋转数组的最小数字(python/c++)
  • 原文地址:https://www.cnblogs.com/yql1986/p/9511831.html
Copyright © 2011-2022 走看看