记一次FastJson报错

文章目录

  • 报错内容
  • 原因探寻
  • 原因及解决方案

报错内容

起因是一段很普通的字符串转Java对象的代码,在本地和内网测试都没有问题,偏偏外网一跑就报错,错误如下:
在这里插入图片描述
报错的代码特别简单,涉及到公司代码这里用测试代码演示,就是将Json字符串转成java对象,示例代码:

List<PojoTest> list = JSONObject.parseObject(json, new TypeReference<>() {});
PojoTest pojo = JSONObject.parseObject(json, PojoTest.class);

PojoTest就是一个特别简单的类:

public class PojoTest {
    private long id;
    private int sn;
    private int num;

    public PojoTest(long id)
    {
        this.id = id;
    }

    public  boolean isGood()
    {
        return id > 100;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public int getSn() {
        return sn;
    }

    public void setSn(int sn) {
        this.sn = sn;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }
}

一个没有默认构造函数的简单对象.

原因探寻

翻看错误日志,可以找到最终报错的代码是ASM试图读取一个class源文件,执行ClassReader构造函数,报了数组越界,ClassReader构造函数源码如下:

    public ClassReader(InputStream is) throws IOException {
        {
        //is是class文件的二进制流
        //这个大括号内的代码是把二进制流读取到this.b的byte数组内
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buf = new byte[1024];
            for (; ; ) {
                int len = is.read(buf);
                if (len == -1) {
                    break;
                }
                if (len > 0) {
                    out.write(buf, 0, len);
                }
            }
            is.close();
            this.b = out.toByteArray();
        }
        //items数组存放的是Class的常量池
        items = new int[readUnsignedShort(8)];
        int n = items.length;
        strings = new String[n];
        // parses the constant pool
        int max = 0;
        int index = 10;
        try {
        //这个for循环就是根据class文件的二进制数组读取常量池并且存放到items数组中
            for (int i = 1; i < n; ++i) {
                items[i] = index + 1;
                int size;
                switch (b[index]) {//报错的就是这一行,index过大导致数组越界
                    case 9: // FIELD:
                    case 10: // METH:
                    case 11: //IMETH:
                    case 3: //INT:
                    case 4: //FLOAT:
                    case 18: //INVOKEDYN:
                    case 12: //NAME_TYPE:
                        size = 5;
                        break;
                    case 5: //LONG:
                    case 6: //DOUBLE:
                        size = 9;
                        ++i;
                        break;
                    case 15: //MHANDLE:
                        size = 4;
                        break;
                    case 1: //UTF8:
                        size = 3 + readUnsignedShort(index + 1);
                        if (size > max) {
                            max = size;
                        }
                        break;
                    // case HamConstants.CLASS:
                    // case HamConstants.STR:
                    default:
                        size = 3;
                        break;
                }
                index += size;
            }
        } catch (Exception e) {
            System.out.println("加载class报错,className:");
            throw e;
        }
        maxStringLength = max;
        // the class header information starts just after the constant pool
        header = index;
    } 

关于字节码相关知识可以查看之前的文章字节码详解.
通过源码可以看出ClassReader初始化报错的代码并没有做其他操作,只是要把class文件对应的常量池读取出来,而读取常量池这个操作也没有任何问题。因为字节码技术保证生成的class文件需要跨平台使用,达到一次编译,到处运行的效果,所以class文件的读取解析方式不会因为平台不同而出现字段不同含义的情况。这个不同平台包括windows与Linux操作系统的不同,也包括大小端的不同,class不管什么样的平台编译,都只会以大端形式存储。
也就是说,只要class正常编译后,都是可以按照大端顺序通过字节顺序读取出来,那上面的报错就只能是class文件格式被修改导致的。

原因及解决方案

开发者本地环境和内网环境之所以没有报错,是因为使用的都是原始的class文件,而为了保证代码安全性,公司运维会在拉取项目jar包时对jar包进行加密,运行时加上-agent解密保证项目本身可以稳定运行。但是对于第三方直接拉取class二进制并按照原始顺序去解析的行为就不支持了,因为加密行为是公司层面为了杜绝代码外泄而进行的,所以不会因为这个报错而选择不加密。
目前最简单的解决方案是:通过修改代码,json转换时确保FastJson不会走asm相关读取class文件的逻辑,比如先将String转成JsonObject对象,再读取对象相关属性赋值到自己的类中,或者保证要转换的java对象有默认构造函数,如例子中的PojoTest类,加上默认构造函数后便不会再报错。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/138586.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java简介

一、Java简介 Java是一门面向对象的编程语言&#xff0c;不仅吸收了C语言的各种优点&#xff0c;还摒弃了C里难以理解的多继承、指针等概念&#xff0c;因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表&#xff0c;极好地实现了面向对象…

国内外四款强大的远控使用体验:ToDesk、向日葵、AnyDesk、Microsoft 远程桌面横向比较

目录 一、引言 二、横测体验 1、ToDesk 2、向日葵 3、AnyDesk安力桌 4、Microsoft 远程桌面 三、评测总结与建议 一、引言 随着科技快速发展和数字化进程的驱动&#xff0c;远程控制软件在日常生活和工作中变得愈加广泛。无论是在家办公、技术支持还是远程教育&#xff…

使用Java实现一个简单的贪吃蛇小游戏

一. 准备工作 首先获取贪吃蛇小游戏所需要的头部、身体、食物以及贪吃蛇标题等图片。 然后&#xff0c;创建贪吃蛇游戏的Java项目命名为snake_game&#xff0c;并在这个项目里创建一个文件夹命名为images&#xff0c;将图片素材导入文件夹。 再在src文件下创建两个包&#xff0…

【rl-agents代码学习】01——总体框架

文章目录 rl-agent Get startInstallationUsageMonitoring 具体代码 学习一下rl-agents的项目结构以及代码实现思路。 source: https://github.com/eleurent/rl-agents rl-agent Get start Installation pip install --user githttps://github.com/eleurent/rl-agentsUsage…

PaaS基础建设

PaaS&#xff08;Platform-as-a-Service&#xff1a;平台即服务&#xff09;是应用程序和服务的部署平台。Paas为开发、测试和管理软件应用程序提供所需的开发环境&#xff0c;是云计算服务类型之一。 PaaS是什么&#xff1f;IaaS、SaaS、PaaS三种云服务区别 PaaS&#xff08;P…

​《水经注全国三维离线GIS系统》硬件安装教程

有些工作&#xff0c;是需要一些外在动力才能完成的。 为什么这么讲呢&#xff1f; 因为正是在客户的要求下&#xff0c;我们才撰写了《水经注全国三维离线GIS系统》的硬件安装教程&#xff0c;而且还录制了视频教程。 当用户收到货物以后&#xff0c;就可以通过本教程清点货…

深度学习AI识别人脸年龄

以下链接来自 落痕的寒假 GitHub - luohenyueji/OpenCV-Practical-Exercise: OpenCV practical exercise GitHub - luohenyueji/OpenCV-Practical-Exercise: OpenCV practical exercise import cv2 as cv import time import argparsedef getFaceBox(net, frame, conf_thresh…

深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)

本章的内容: 什么是函数栈帧&#xff1f; 理解函数栈帧能解决什么问题&#xff1f; 函数栈帧的创建和销毁解析 本文放到 --> 该专栏内&#xff1a;http://t.csdnimg.cn/poMzA 目录 什么是函数栈帧❓ 理解函数栈帧能解决什么问题呢&#xff1f;&#x1f4a2; 函数栈帧的…

计数排序及优化

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f43b;‍❄个人主页&#x1f389;&#xff1a;GOTXX&#x1f43c;个人WeChat&#xff1a;ILXOXVJE&#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&a…

汽车一键启动智能系统功能作用

在现代科技的推动下&#xff0c;我们的生活每天都在发生着变化。其中&#xff0c;汽车智能一键启动系统就是科技改变生活的最好例子之一。 首先&#xff0c;我们来简单了解一下汽车智能一键启动系统。它是一种利用先进的电子技术和无线通信技术&#xff0c;实现无需钥匙即可启…

基于单片机智能输液器监控系统的设计

**单片机设计介绍&#xff0c; 基于单片机智能输液器监控系统的设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的智能输液器监控系统可以实现对输液过程的实时监测和控制&#xff0c;以下是一个基本的设计介绍&am…

【数据结构——队列的实现(单链表)】

数据结构——队列的实现&#xff08;单链表&#xff09; 一.队列1.1队列的概念及结构 二.队列的实现2.1 头文件的实现——&#xff08;Queue.h&#xff09;2.2 源文件的实现—— &#xff08;Queue.c&#xff09;2.3 源文件的实现—— &#xff08;test.c&#xff09; 三.队列的…

拼多多API接口,打造智能化电商平台

近年来&#xff0c;电商行业的崛起给人们的购物带来了极大的方便。随着电商行业的发展&#xff0c;拼多多作为新兴电商平台已经成为市场焦点。 同时&#xff0c;随着技术的发展&#xff0c;API&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&…

pta 6翻了 Python3

“666”是一种网络用语&#xff0c;大概是表示某人很厉害、我们很佩服的意思。最近又衍生出另一个数字“9”&#xff0c;意思是“6翻了”&#xff0c;实在太厉害的意思。如果你以为这就是厉害的最高境界&#xff0c;那就错啦 —— 目前的最高境界是数字“27”&#xff0c;因为这…

云课五分钟的一些想法

起源 自中学起&#xff0c;就积极学习和掌握互联网相关知识&#xff0c;到如今已经快30年了。 个人也全程经历了从信息时代的互联网&#xff08;硬&#xff09;到智能时代的大模型&#xff08;软&#xff09;。 整体信息到智能的基础设施&#xff0c;由硬到软&#xff0c;机…

CRM系统:除了销售管理,还能做些什么?

企业的健康发展&#xff0c;离不开业绩的提升。在企业数字化转型的背景下&#xff0c;采用数字化应用进行管理已成为共识。许多企业认识到了应该使用CRM客户管理系统来进行销售管理&#xff0c;但CRM能做的还有很多。下面说说除了销售管理&#xff0c;CRM系统还能做些什么&…

继承和多态_Java零基础手把手保姆级教程(超详细)

文章目录 Java零基础手把手保姆级教程_继承和多态&#xff08;超详细&#xff09;1. 继承1.1 继承的实现&#xff08;掌握&#xff09;1.2 继承的好处和弊端&#xff08;理解&#xff09; 2. 继承中的成员访问特点2.1 继承中变量的访问特点&#xff08;掌握&#xff09;2.2 sup…

石英增强光声光谱气体传感技术中的高精密压力控制解决方案

摘要&#xff1a;光声池内气体压力的可调节控制以及稳定性是保证光声法高精度测量的关键&#xff0c;但在目前的光声和光谱研究中&#xff0c;对气体样品池内压力控制技术的报道极为简单&#xff0c;甚至很多都是错误的&#xff0c;根本无法实现高精度调节和控制&#xff0c;为…

Autosar模块介绍:Memory_3(MemIf-内存接口抽象)

上一篇 | 返回主目录 | 下一篇 Autosar模块介绍&#xff1a;Memory_3(MemIf-内存接口抽象 1 基本术语解释2 MemIf组成结构图 1 基本术语解释 编号缩写原文解释1(Logical) Block——可单独寻址的连续内存区域&#xff08;即&#xff0c;用于读、写、擦除、比较等操作&#xff…

眼科动态图像处理系统使用说明(2023-8-11 ccc)

眼科动态图像处理系统使用说明 2023-8-11 ccc 动态眼科图像捕捉存贮分析与传输系统&#xff0c;是由计算机软件工程师和医学专家组结合&#xff0c;为满足医院临床工作的需要&#xff0c;在2000年开发的专门用于各类眼科图像自动化分析、处理和传输的软件系统。该系统可以和各…