美文网首页
Json4s 版本不兼容问题分析

Json4s 版本不兼容问题分析

作者: WestC | 来源:发表于2019-10-09 13:15 被阅读0次

问题现象:

应用基于Spark2.3编译,在编译时添加了依赖json4s的包,指定版本为3.2.10,在提交spark作业后,抛出如下

java.lang.NoSuchMethodError: org.json4s.jackson.JsonMethods$.render(Lorg/json4s/JsonAST$JValue;)Lorg/json4s/JsonAST$JValue;

问题分析

json4s项目出现小版本间api不兼容

查看相关lib下的jar包,可以确认json4s-jackson_2.11-3.2.10.jar的jar包,不应当找不到该jar包。

于是怀疑jar包冲突,查看Spark服务相关目录的jar包发现存在json4s-jackson_2.11-3.2.11.jar,因此怀疑该jar包版本不一致,发生冲突。

正常来讲,小版本的变更不应当发生接口不兼容的情况,然而,google一下就发现确实是json4s项目的版本不兼容问题。

json4s项目的源码与jar包不对应

于是查看一下json4s在3.2.10以及3.2.11版本的的JsonMethods类:

// 3.2.10
def render(value: JValue): JValue = value
// 3.2.11
def render(value: JValue): JValue = value
// 3.2.11-2.10 或3.2.11-2.12
def render(value: JValue)(implicit formats: Formats = DefaultFormats): JValue =
    formats.emptyValueStrategy.replaceEmpty(value)

由于应用编译时依赖的是scala2.11版本,如果仅仅从代码上分析,并不会出现不兼容的情况。

于是进一步查看spark服务中依赖的json4s的jar包,反编译之后分析可以看出,其使用的源码应当是3.2.11-2.10或3.2.11-2.12版本,这又是json4s的坑了

查看两个版本反编译之后的代码,可以很明确的看出在3.2.11版本中确实不存在 org.json4s.jackson.JsonMethods$.render(Lorg/json4s/JsonAST$JValue;)Lorg/json4s/JsonAST$JValue 方法

image ​ image

问题复现

即使使用以上不同代码,如果应用程序代码中依旧可以调用不同版本的json4s,因为对于带有隐式参数的render函数来说,由于其包含了default值,我们依旧可以通过调用render(JValue)来调用。于是测了一把带有隐式默认值的函数的调用。

测试函数如下 :

  1. 带有隐式默认参数的函数(code1)

    package com.cyq.test
    trait TClass {
      def fun(a : Any)(implicit b : String = "abcd") : Unit = {
        println("Enter in class impl")
      }
    }
    object TClass  extends TClass
    
  1. 不带有隐式默认参数的函数(code2)

    package com.cyq.test
    trait TClass {
     def fun(a : Any): Unit = {
       println("Enter in class without impl")
     }
    }
    object TClass  extends TClass
    
  2. 测试函数(code3)

    object MyTest {
       def main(args: Array[String]): Unit = {
    
         println("Starting")
         TClass.fun(100)
         println("End")
       }
    }
    
  3. 测试步骤

    1. 基于code1,code2 分别打包为TestWithImpl.jar,TestWithoutImpl.jar

    2. 基于TestWithoutImpl.jar 将code3打包为NoMethodTest.jar

    3. 分别运行如下命令,问题得以复现:

      image
  1. 基于TestWithImpl.jar 将code3打包为NoMethodTest.jar

  2. 分别运行如下命令,问题得以解决:

    image

解决方案

基于应用代码,不做修改,选择3.2.11版本的json4s版本,重新编译即可。

结论

基于不同依赖版本的jar包编译的编译出来的应用程序(jar包),可能由于依赖版本的不兼容,导致运行异常。

相关文章

网友评论

      本文标题:Json4s 版本不兼容问题分析

      本文链接:https://www.haomeiwen.com/subject/vlzwpctx.html