出现问题
在一次需求迭代中,只是改了某个接口的内容,但在预发环境构建之后居然发现调用接口出现java.lang.NoSuchMethodError: kotlin.collections.ArraysKt.copyInto([B[BIII)[B 的错误。
查找原因
通过查找日志发现,这是我使用的forest网络框架提示出来的,如下:
java.lang.NoSuchMethodError: kotlin.collections.ArraysKt.copyInto([B[BIII)[B
at okio.Buffer.write(Buffer.kt:1640)
at okio.RealBufferedSink.write(RealBufferedSink.kt:174)
at okhttp3.RequestBody$2.writeTo(RequestBody.java:98)
at com.dtflys.forest.backend.okhttp3.logging.OkHttp3LogBodyMessage.getLogContentForStringBody(OkHttp3LogBodyMessage.java:42)
at com.dtflys.forest.backend.okhttp3.logging.OkHttp3LogBodyMessage.getBodyString(OkHttp3LogBodyMessage.java:141)
at com.dtflys.forest.logging.DefaultLogHandler.requestLoggingBody(DefaultLogHandler.java:51)
at com.dtflys.forest.logging.DefaultLogHandler.requestLoggingContent(DefaultLogHandler.java:117)
at com.dtflys.forest.logging.DefaultLogHandler.logRequest(DefaultLogHandler.java:169)
at com.dtflys.forest.backend.okhttp3.executor.AbstractOkHttp3Executor.logRequest(AbstractOkHttp3Executor.java:110)
at com.dtflys.forest.backend.okhttp3.executor.AbstractOkHttp3Executor.execute(AbstractOkHttp3Executor.java:187)
at com.dtflys.forest.backend.okhttp3.executor.AbstractOkHttp3Executor.execute(AbstractOkHttp3Executor.java:288)
at com.dtflys.forest.http.ForestRequest.execute(ForestRequest.java:1687)
at com.dtflys.forest.http.ForestRequest.execute(ForestRequest.java:1704)
at com.dtflys.forest.reflection.ForestMethod.invoke(ForestMethod.java:1175)
at com.dtflys.forest.proxy.InterfaceProxyHandler.invoke(InterfaceProxyHandler.java:126)
at com.sun.proxy.$Proxy174.createYonYouOrder(Unknown Source)
请教了一下forest的作者,告诉我这应该是okio和okhttp的包冲突导致的,其实事后详细从上面的日志也不难看出来。
可是我百思不得其解,我并没有更新pom文件,也就是并没有引入新的包进来,理论上应该还是和上一个版本一样的,但上一个版本是正常的,虽然很难理解,但我还是去对比正式环境和预发布环境看看这两个jar分别是什么版本的。
进入容器可使用以下命令查看引用的依赖jar的版本,当然其实如果你把应用jar包解压出来去看也是可以的。
jar tf app.jar |grep okio
jar tf app.jar |grep okhttp
这里发现正式环境和预发环境的okhttp的版本是一样的,但okio的版本不一样,预发的是2.7.0,而正式的则是1.50.0。
这还真奇了怪了,没有更新maven依赖怎么会导致这样的结果呢,于是我在idea里面去查找okio这个依赖。
idea查找依赖的关系和版本
在pom.xml文件里面右键Maven→Show Dependencies... 或者使用快捷键Ctrl+Alt+Shift+U,会生成maven依赖关系图。
然后Ctrl+F查找okio.
确实有两个,逐个去看了,那个高版本的是华为云的一个包依赖的。
然后我去看了下pom里面那个依赖引入是这样写的:
<dependency>
<groupId>com.huaweicloud</groupId>
<artifactId>esdk-obs-java</artifactId>
<version>[3.19.7,)</version>
</dependency>
这里的version指定的是[3.19.7,),意思是版本>=3.19.7,并取最新的发布版本,所以导致预发重新构建出来的版本不一样了,我再次去预发和正式环境查看了一下这个包的版本,确实是这样的。正式esdk-obs-java版本是3.21.4.1而预发是3.21.8。
解决方案
原因找到了,解决也就容易了。有两个办法,一是固定esdk-obs-java版本为3.21.4.1,二是升级okhttp版本使得和okio版本对应。
这里选择了第一个办法,因为可快速解决,并且升级okhttp也担心会有其他问题,还需要测试验证。