美文网首页
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