记一次JSON.toJSONString()踩坑

debug时发现toJSONString()总是抛出空指针异常,但能正常运行,结果也正确

环境:JDK1.8
com.alibaba.fastjson:1.2.46

public static void main(String[] args) {
		JSONObject obj = new JSONObject();
		obj.put("key1","value1");
		String jsonString = obj.toJSONString();
		System.out.println("json字符串:"+jsonString);
	}

在JSON.toJSONString()方法上打断点,以debug模式启动

看到执行到return out.toString抛出了NullPointerException,out对象中的buf已经为空:

记一次JSON.toJSONString()踩坑

但toJSONString()的返回结果是正确的:

记一次JSON.toJSONString()踩坑

再次debug发现:
如果try{}中有return,那么执行到return那条语句时,会计算return后面的表达式,作为返回值存起来但不return。
去执行finally{}再继续执行return后面的表达式,再return,于是方法结束。

在JSON.toJSONString()和SerializeWriter.toString()方法上打断点,debug启动:

记一次JSON.toJSONString()踩坑

记一次JSON.toJSONString()踩坑

记一次JSON.toJSONString()踩坑

从这一步可以看出此时执行了return后面的表达式:out.toString()

接下来进入finally块:
记一次JSON.toJSONString()踩坑

这一步执行out.close(),out.close()源代码如下:

记一次JSON.toJSONString()踩坑

它进行了一系列操作后,将buf设置为null。
执行完finally块,程序又回到了return那一行,然后抛出了NullPointerException:

记一次JSON.toJSONString()踩坑

总结一下,执行顺序是这样的:

记一次JSON.toJSONString()踩坑

因为第3步将out对象的buf置为了null,但第4步又调用了out.toString(),这个方法又用到了buf.length,所以就抛出了NullPointerException。
但又由于第2步已经将返回值暂存了起来,所以返回值是正常的。

后来我又去下载fastjson最新版1.2.73,代码已经更新为:

记一次JSON.toJSONString()踩坑

这版无异常,返回结果也正确。

上一篇:此字段需要一个合法的 64 位无符号整数


下一篇:ctrip