fastjson在kotlin+java混合项目中的bug

fastjson在kotlin+java混合项目中的bug

环境

kotlin 1.3 + java 8 + fastjson 1.2.62

问题

最近在项目中遇到一个问题,测试小伙伴反馈在测试环境用着用着突然就接口调用失败,查看日志是报这个错误:


image

试了一下其他接口,也是一样的问题,可就在几分钟前还一切OK,开发本地调试也一切完好,就访问云端的镜像报错。找这个报错的原因,已经写得很明白了,fastjson反序列化时没有找到默认构造函数。

看起来似乎是在调用云端镜像时某个时刻触发了一个事件,导致云端应用状态变化,进而导致后续的接口调用失败。

基于此猜测我们重启了云端应用进行验证,果不其然,重启后一切恢复正常。那么是触发了什么事件导致后续调用失败呢?

于是开发小哥尝试复现问题,正在尝试复现,测试小伙伴又反馈报错了,赶紧抓住现场!

一番沟通后还原测试小伙伴的操作,果然,某个操作会导致一个异常:


image

出现此异常后,后续的接口调用都会失败。但此异常不影响业务,所以在客户端不易被察觉。

原因分析

分析上诉抛出的异常是在fastjson的TypeUtils.java中:


image

进一步分析,为什么constructor为null?

留意一下发现这里clazz变量的类型时kotlin.Unit,这相当于java中的void

/**
 * The type with only one value: the `Unit` object. This type corresponds to the `void` type in Java.
 */
public object Unit {
    override fun toString() = "kotlin.Unit"
}

用了object关键字进行对象声明,是不带构造函数的,所以迭代器变量it中没有迭代对象,constructor就为null了。于是代码逻辑进入到catch,在catch中会把kotlin_error置为true,后续的请求到这里就直接返回null了:


image

为什么会出现kotlin.Unit的序列化操作呢?

kotlin默认把没有返回值的函数当做返回kotlin.Unit,如果把没有返值的函数丢给fastjson反序列化就会导致此问题。