欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Maven故障排查 博客分类: pinpoint

程序员文章站 2024-02-22 09:35:58
...

最近在使用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

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

Maven故障排查
            
    
    博客分类: pinpoint
 

第八步,重新开始调试。这时候我们发现断点停留在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命令行。

Maven故障排查
            
    
    博客分类: pinpoint
 

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

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提示考虑不足吧!

 

 

 

 

 

 

 

  • Maven故障排查
            
    
    博客分类: pinpoint
  • 大小: 16.1 KB
  • Maven故障排查
            
    
    博客分类: pinpoint
  • 大小: 31 KB