记一次fastjson空指针异常

简介: 案例:package com;import com.alibaba.fastjson.JSONObject;import lombok.Data;import java.nio.charset.StandardCharsets;@Datapublic class User {    private Long id;    private String name;    

案例:

package com;

import com.alibaba.fastjson.JSONObject;
import lombok.Data;

import java.nio.charset.StandardCharsets;

@Data
public class User {

    private Long id;

    private String name;

    private String a;

    public byte[] getBytes() {
        return a.getBytes(StandardCharsets.UTF_8);
    }

    public static void main(String[] args) {
        User user = new User();
        user.setName("");
        user.setId(1L);
        String a = JSONObject.toJSONString(user);
    }
}

问题:

getBytes方法虽然有空指针问题,但是没有被调用到不应该报空指针错误。

原因:

fastjson扫描被序列化的类的所有的属性和getXxx方法,将属性和xxx做为新生成的类的新属性,JSONObject.toJSONString获取所有属性时会调用getBytes来获取bytes属性,getBytes方法本身导致的空指针就会报错。

fastJson源码分析:

JSON#toJSONString

调用com.alibaba.fastjson.JSON#toJSONString(java.lang.Object, com.alibaba.fastjson.serializer.SerializeConfig, com.alibaba.fastjson.serializer.SerializeFilter[], java.lang.String, int, com.alibaba.fastjson.serializer.SerializerFeature...)方法

JSONSerializer#write(java.lang.Object)

SerializeConfig#getObjectWriter(java.lang.Class<?>, boolean)

SerializeConfig#createJavaBeanSerializer(java.lang.Class<?>)

获取原class信息

TypeUtils#buildBeanInfo(java.lang.Class<?>, java.util.Map<java.lang.String,java.lang.String>, com.alibaba.fastjson.PropertyNamingStrategy, boolean)

TypeUtils#computeGetters(java.lang.Class<?>, com.alibaba.fastjson.annotation.JSONType, java.util.Map<java.lang.String,java.lang.String>, java.util.Map<java.lang.String,java.lang.reflect.Field>, boolean, com.alibaba.fastjson.PropertyNamingStrategy)

TypeUtils#computeFields

生成新class

SerializeConfig#createJavaBeanSerializer(com.alibaba.fastjson.serializer.SerializeBeanInfo)

SerializeConfig#createASMSerializer

ASMSerializerFactory#createJavaBeanSerializer

SerializeConfig#createJavaBeanSerializer(com.alibaba.fastjson.serializer.SerializeBeanInfo)

将新class生成string

JSONSerializer#write(java.lang.Object)

JavaBeanSerializer#JavaBeanSerializer(com.alibaba.fastjson.serializer.SerializeBeanInfo)

JavaBeanSerializer#write(com.alibaba.fastjson.serializer.JSONSerializer, java.lang.Object, java.lang.Object, java.lang.reflect.Type, int, boolean)

FieldSerializer#getPropertyValueDirect

FieldInfo#get

思考和总结

  1. 编写方法时不应该假设某些值一定会存在,在有些不熟悉的代码中可能绕过了你原本的逻辑,在每个方法中都做好防御编程。
  2. 使用ASM生成新字节码的方式是否有更好的打印堆栈方式,提供给开发者更清晰的原因,方便排查问题。
  3. 多熟悉自己使用的第三方库,对执行方式有一定的了解。

相关文章
|
5月前
|
资源调度 监控 关系型数据库
实时计算 Flink版操作报错合集之处理大量Join时报错空指针异常,是什么原因
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
实时计算 Flink版操作报错合集之处理大量Join时报错空指针异常,是什么原因
|
8月前
|
Kubernetes 关系型数据库 MySQL
seata启动问题之指针异常如何解决
Seata是一款开源的分布式事务解决方案,旨在提供高效且无缝的分布式事务服务;在集成和使用Seata过程中,开发者可能会遇到不同的异常问题,本合集针对Seata常见异常进行系统整理,为开发者提供详细的问题分析和解决方案,助力高效解决分布式事务中的难题。
357 9
|
6月前
|
运维
系统日志使用问题之如何防止在打印参数时遇到NPE(空指针异常)
系统日志使用问题之如何防止在打印参数时遇到NPE(空指针异常)
java.lang.NullPointerExceptionMybatisPlus出现,测试,java.lang.NullPointe,空指针异常,public方法少写了一个字段,没加注解
java.lang.NullPointerExceptionMybatisPlus出现,测试,java.lang.NullPointe,空指针异常,public方法少写了一个字段,没加注解
|
8月前
|
存储 Java 开发者
探索Java开发中触发空指针异常的场景
作为一名后端开发者在Java编程的世界中,想必大家对空指针并不陌生,空指针异常是一种常见而又令人头疼的问题,它可能会在我们最不经意的时候突然出现,给我们的代码带来困扰,甚至导致系统的不稳定性,而且最可怕的是有时候不能及时定位到它的具体位置。针对这个问题,我们需要深入了解触发空指针异常的代码场景,并寻找有效的方法来识别和处理这些异常情况,而且我觉得空指针异常是每个Java开发者都可能面临的挑战,但只要我们深入了解它的触发场景,并采取适当的预防和处理措施,我们就能够更好地应对这个问题。那么本文就来分享一下实际开发中一些常见的触发空指针异常的代码场景,并分享如何有效地识别和处理这些异常情况。
114 1
探索Java开发中触发空指针异常的场景
|
8月前
|
Java 容器
自定义数据类型中的空指针异常
自定义数据类型中的空指针异常
56 2
|
8月前
|
Oracle 安全 Java
Seata常见问题之启动seata一直报空指针异常如何解决
Seata 是一个开源的分布式事务解决方案,旨在提供高效且简单的事务协调机制,以解决微服务架构下跨服务调用(分布式场景)的一致性问题。以下是Seata常见问题的一个合集
项目中常见NPE空指针异常
项目中常见NPE空指针异常
|
8月前
|
安全 IDE Java
终结空指针异常:Java开发者的生存指南
终结空指针异常:Java开发者的生存指南
193 1
|
8月前
|
安全 IDE Java
【2024java面试题无需C币下载】终结空指针异常:Java开发者的生存指南
【2024java面试题无需C币下载】终结空指针异常:Java开发者的生存指南
95 1