`
sswh
  • 浏览: 161728 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

Maven故障排查

 
阅读更多

最近在使用pinpoint-2.7,在调试某些模块源码时,发现在Maven-Install步骤总是会失败。

但Maven的错误提示语焉不详。例如下面:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.5.1:testCompile (default-testCompile) on project pinpoint-bootstrap: Compilation failure -> [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.

 即使我们打开Maven的 Debug Output(-X)详细错误日志,仍然什么都看不到。

郁闷之极。

 

实在没有办法,只能祭出“断点调试”这最后一步棋了!

第一步,我们找到出错的插件和目标:org.apache.maven.plugins:maven-compiler-plugin:3.5.1:testCompile

 

第二步,新建一个demo工程,我们把错误插件添加到Maven依赖中来

<dependency>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-compiler-plugin</artifactId>
	<version>3.5.1</version>
	<scope>provided</scope>
</dependency>

 

第三步,找到maven-compiler-plugin-3.5.1.jar中插件定义plugin.xml文件,搜索“testCompile”目标,

找到它的实现类:

<implementation>org.apache.maven.plugin.compiler.TestCompilerMojo</implementation>

 然后,在TestCompilerMojo的execute()方法上打上断点

 

第四步,首先在项目上右键:Run As - Maven-Install,产生一个运行配置。

然后,在Eclipse的调试配置中,找到刚产生的运行配置,注意在“Maven Build”下面。

在目标中输入“clean install”

点击调试按钮。这时候,Maven运行会停在断点位置。但是会找不到源代码。

 

 第五步,我们把源代码关联进来。首先在demo项目上,执行Maven - Download Sources,

把依赖部分的源码下载下来。

然后,回到上一步的调试配置,打开“Source”标签页,用Add方法添加源码搜索路径:

M2_REPO/org/apache/maven/plugins/maven-compiler-plugin/3.5.1/maven-compiler-plugin-3.5.1.jar

 注意,不要上面添加的不是-sources.jar文件。(好处是调试时,在display视图中可以直接执行代码片段)

 

第六步,重新执行debug  clean install,这时候,我们发现断点停留在TestCompilerMojo.execute()方法

对应行。我们沿着调用栈向上寻找,找到最近的catch(Exception)的代码位置,我们加上断点。

这儿找到的位置是:MojoExecutor.java

try
{
	pluginManager.executeMojo( session, mojoExecution );
}
catch ( MojoFailureException | PluginManagerException | PluginConfigurationException
	| MojoExecutionException e )
{
	throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), e );
}

 

第七步,继续执行,这时候,我们发现断点停留在catch后的位置,

我们点开变量视图,查看此时的异常对象类型,发现是:org.apache.maven.plugin.compiler.CompilationFailureException

然后,我们进入断点视图,添加对应的“异常断点”。


 

第八步,重新开始调试。这时候我们发现断点停留在org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute()方法上。

根据代码,我们知道,当warnings为空的时候,将丢出此异常。

继续向上快速阅读源码,我们知道 当compilerResult返回false时,会触发编译失败异常,这也很容易理解。

 

第九步,我们找到CompilerResult这个类的代码(maven会自动下载打开类的代码),

找到success字段,将这个字段的写操作添加到断点中。

 

第十步,重启调试,这次断点停留在CompilerResult的构造函数(<init>方法)上。

我们查看java栈,找到下一个调用方法,发现断点停留在:

org.codehaus.plexus.compiler.javac.JavacCompiler.compileOutOfProcess()方法。

这也很容易理解了,Maven 编译过程调用了外部的JavaC命令行。


 

第十一步,我们找到了核心执行语句:

returnCode = CommandLineUtils.executeCommandLine( cli, out, err );

 这时候查看 cli 的参数,其值类似于:

cmd.exe /X /C "D:\eclipse4oschina\jdk1.6.0_23\bin\javac @C:/Users/caohj/AppData/Local/Temp/org.codehaus.plexus.compiler.javac.JavacCompiler8877254923779120414arguments"

 

 第十二步,我们打开一个新的CMD窗口,把cmd命令拷贝出来,放在命令行执行。

这时候我们终于看到了错误提示:

错误:读取 D:\m2\net\bytebuddy\byte-buddy\1.6.11\byte-buddy-1.6.11.jar 时出错;
invalid LOC header (bad signature)
1 错误

 原来,罪魁祸首是Maven在下载byte-buddy库时出现了错误。

我们删除对应的JAR,然后回到Eclipse中,在项目上右键 Maven - Update Project,重新下载需要的JAR

我们发现,两次下载的JAR文件果然大小不一样。

重新执行 Maven-Install, 故障排除。

 

 ---------------------------------------------------------

故障排除后,我们来看一下,为什么Maven没有提示出编译错误呢?

我们重新把错误的byte-buddy  JAR包还原,再次进入调试。

断点跟踪,终于发现问题所在:plexus-compiler-javac/2.7版的

org.codehaus.plexus.compiler.javac.JavacCompiler.parseModernStream()方法

在解析JavaC命令行错误时,有一处关键语句:

if ( ( buffer.length() == 0 ) && line.startsWith( "error: " ) )
{
	errors.add( new CompilerMessage( line, true ) );
}

 但是命令行返回的提示却是:

错误:读取 D:\m2\net\bytebuddy\byte-buddy\1.6.11\byte-buddy-1.6.11.jar 时出错;invalid LOC header (bad signature)

 “error:” 和 "错误:" ----- 这可能是对中文版JavaC提示考虑不足吧!

 

 

 

 

 

 

 

  • 大小: 16.1 KB
  • 大小: 31 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics