背景
在使用CICD进行构建时,第一次构建成功,第二次之后就一直失败,异常信息如下:
[ERROR] Malformed \uxxxx encoding.
java.lang.IllegalArgumentException: Malformed \uxxxx encoding.
at java.util.Properties.loadConvert (Properties.java:574)
at java.util.Properties.load0 (Properties.java:390)
at java.util.Properties.load (Properties.java:341)
at org.eclipse.aether.internal.impl.TrackingFileManager.read (TrackingFileManager.java:64)
at org.eclipse.aether.internal.impl.DefaultUpdateCheckManager.read (DefaultUpdateCheckManager.java:511)
at org.eclipse.aether.internal.impl.DefaultUpdateCheckManager.checkMetadata (DefaultUpdateCheckManager.java:252)
at org.eclipse.aether.internal.impl.DefaultMetadataResolver.resolve (DefaultMetadataResolver.java:302)
at org.eclipse.aether.internal.impl.DefaultMetadataResolver.resolveMetadata (DefaultMetadataResolver.java:181)
at org.apache.maven.repository.internal.DefaultVersionRangeResolver.getVersions (DefaultVersionRangeResolver.java:198)
at org.apache.maven.repository.internal.DefaultVersionRangeResolver.resolveVersionRange (DefaultVersionRangeResolver.java:148)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.cachedResolveRangeResult (DefaultDependencyCollector.java:622)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.processDependency (DefaultDependencyCollector.java:395)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.processDependency (DefaultDependencyCollector.java:365)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.process (DefaultDependencyCollector.java:352)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.doRecurse (DefaultDependencyCollector.java:509)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.processDependency (DefaultDependencyCollector.java:461)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.processDependency (DefaultDependencyCollector.java:365)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.process (DefaultDependencyCollector.java:352)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.doRecurse (DefaultDependencyCollector.java:509)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.processDependency (DefaultDependencyCollector.java:461)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.processDependency (DefaultDependencyCollector.java:365)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.process (DefaultDependencyCollector.java:352)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.doRecurse (DefaultDependencyCollector.java:509)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.processDependency (DefaultDependencyCollector.java:461)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.processDependency (DefaultDependencyCollector.java:365)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.process (DefaultDependencyCollector.java:352)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.doRecurse (DefaultDependencyCollector.java:509)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.processDependency (DefaultDependencyCollector.java:461)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.processDependency (DefaultDependencyCollector.java:365)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.process (DefaultDependencyCollector.java:352)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.doRecurse (DefaultDependencyCollector.java:509)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.processDependency (DefaultDependencyCollector.java:461)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.processDependency (DefaultDependencyCollector.java:365)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.process (DefaultDependencyCollector.java:352)
at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.collectDependencies (DefaultDependencyCollector.java:254)
at org.eclipse.aether.internal.impl.DefaultRepositorySystem.collectDependencies (DefaultRepositorySystem.java:284)
at org.apache.maven.project.DefaultProjectDependenciesResolver.resolve (DefaultProjectDependenciesResolver.java:169)
at org.apache.maven.lifecycle.internal.LifecycleDependencyResolver.getDependencies (LifecycleDependencyResolver.java:243)
at org.apache.maven.lifecycle.internal.LifecycleDependencyResolver.resolveProjectDependencies (LifecycleDependencyResolver.java:147)
at org.apache.maven.lifecycle.internal.MojoExecutor.ensureDependenciesAreResolved (MojoExecutor.java:248)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:202)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:498)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
思路一
先看看别人有没有遇到过,简单的说,先面向搜索引擎解决问题
搜索得到的结果如下:
- 清空本地maven仓库重新编译,因CICD的仓库不能动,PASS
- 检查代码、配置文件中是否有带着 "\" 字符的问题路径,修改成 "/",查无这样的现象,PASS
思路二
别人的方法不管用,就只能自己上了,从上述搜索结果看,别人能通过这种问题解决,无非是maven仓库有问题,或者代码有问题
1、首先想到,本地打包没问题,那基本可以排除是代码的问题
2、maven仓库有问题,得看看maven的jar包更新策略,然后我找到了
3、受文章启发,我想到乱码可能出在 resolver-status.properties 文件,因为只有这个文件是maven写入本地仓库的
4、于是我本着试一试的态度去maven的issue搜了一下 resolver-status.properties
,然后,很巧的是我就看到了
5、大致上,是说 resolver-status.properties 会因为并发写入而损坏
6、于是我回到 CICD 的构建日志中,找到了出错位置上方DEBUG信息,信息如下:
[DEBUG] Could not find metadata org.glassfish:javax.el/maven-metadata.xml in local (/data/repo)
7、结合2步骤的文章,推测是 org.glassfish:javax.el 的 resolver-status.properties 因为并发写入而损坏导致的问题
8、于是我联系CICD的运维人员,让他帮我看一下 org.glassfish:javax.el 下的 resolver-status.properties 是否存在乱码
9、最终确定是该文件乱码,删除后重新构建成功
思考
1、什么情况下会产生 resolver-status.properties
从远程仓库拉取jar包的时候,maven会更新该元文件,并且每次拉取都会更新。该文件主要作用是记录maven-metadata--nexus.xml 文件的上次更新时间戳,并结合标签完成更新策略的一部分。
2、什么情况下 resolver-status.properties 会有并发写入
从思路二的第4步,可以看到,maven 最初对该文件的写入是有加同步锁的,只是在 https://github.com/apache/maven-resolver/pull/67 之后,同步已在TrackingFileManager上被删除,而 DefaultMetadataResolver线程尝试并发写入该文件
3、怎么彻底解决 resolver-status.properties 的并发写入问题
构建命令中加入 -Daether.metadataResolver.threads=1, 该参数的含义是保证对 resolver-status.properties 的操作是单线程的
Mave-resolver 1.6.x 中提供了解决办法,可以在构建命令中加入
-Dspot_file_with_malformed_encoding=true
来解决该问题