JEP290深入学习

news2024/11/26 7:25:50

关键类的学习

ObjectInputFilter

serialFilter字段的类型就是ObjectInputFilter,这个接口是一个函数接口(可以对方法进行赋值),其中定义的抽象方法是:

Status checkInput(FilterInfo filterInfo);

接受的参数类型FilterInfo是内部的一个接口,封装了各种过滤的信息:

interface FilterInfo {
        /**
         * The class of an object being deserialized.
         * For arrays, it is the array type.
         * For example, the array class name of a 2 dimensional array of strings is
         * "{@code [[Ljava.lang.String;}".
         * To check the array's element type, iteratively use
         * {@link Class#getComponentType() Class.getComponentType} while the result
         * is an array and then check the class.
         * The {@code serialClass is null} in the case where a new object is not being
         * created and to give the filter a chance to check the depth, number of
         * references to existing objects, and the stream size.
         *
         * @return class of an object being deserialized; may be null
         */
        Class<?> serialClass();

        /**
         * The number of array elements when deserializing an array of the class.
         *
         * @return the non-negative number of array elements when deserializing
         * an array of the class, otherwise -1
         */
        long arrayLength();

        /**
         * The current depth.
         * The depth starts at {@code 1} and increases for each nested object and
         * decrements when each nested object returns.
         *
         * @return the current depth
         */
        long depth();

        /**
         * The current number of object references.
         *
         * @return the non-negative current number of object references
         */
        long references();

        /**
         * The current number of bytes consumed.
         * @implSpec  {@code streamBytes} is implementation specific
         * and may not be directly related to the object in the stream
         * that caused the callback.
         *
         * @return the non-negative current number of bytes consumed
         */
        long streamBytes();
    }

这个接口作为一个函数接口,更多的情况下是作为方法引用存在的,比如在RMI中的:

RegsitryImpl::registryFilter

ObjectInputFilter.Config

static / createFilter

Config类的静态代码块中会初始化其内部字段configuredFilter,这个字段会被赋值给serialFilter

从代码上来看,首先会获取一个叫SERIAL_FILTER_PROPNAME的常量(其值是jdk.serialFilter),如果结果不为null的话就传入createFilter方法:

public static ObjectInputFilter createFilter(String pattern) {
  	Objects.requireNonNull(pattern, "pattern");
  	return Global.createFilter(pattern, true);
}

这里又涉及到了Global (implements) ObjectInputFilter这个类,根据官方注释,Global#createFilter方法的作用就是把字符串解析成一个ObjectInputFilter对象(Returns an ObjectInputFilter from a string of patterns),具体分析见后文的Global部分。

get(set)SerialFilter

从方法名字就可以看出来,它们是serialFilter字段的getter和setter方法。

public static ObjectInputFilter getSerialFilter() {
  	synchronized (serialFilterLock) {
    	return serialFilter;
  	}
}
public static void setSerialFilter(ObjectInputFilter filter) {
    Objects.requireNonNull(filter, "filter");
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        sm.checkPermission(new SerializablePermission("serialFilter"));
    }
    synchronized (serialFilterLock) {
        if (serialFilter != null) {
            throw new IllegalStateException("Serial filter can only be set once");
        }
        serialFilter = filter;
    }
}

get(set)ObjectInputFilter

获取(初始化)一个ObjectInputStream对象中的ObjectInputFilter类型的字段(即serialFilter)。

public static ObjectInputFilter getObjectInputFilter(ObjectInputStream inputStream) {
    Objects.requireNonNull(inputStream, "inputStream");
    return sun.misc.SharedSecrets.getJavaOISAccess().getObjectInputFilter(inputStream);
}
public static void setObjectInputFilter(ObjectInputStream inputStream,
                                        ObjectInputFilter filter) {
    Objects.requireNonNull(inputStream, "inputStream");
    sun.misc.SharedSecrets.getJavaOISAccess().setObjectInputFilter(inputStream, filter);
}

ObjectInputFilter.Config.Global

Global类是Config内部的静态类,实现了ObjectInputFilter接口,内部也有chekInput()方法的实现,所以可以把Global类的对象看作是一个过滤器,它可以直接赋值到ObjectInputStream.serialFilter字段上。

checkInput

Global类的内部有一个储存filter的列表:

private final List<Function<Class<?>, Status>> filters;

checkInput()方法中会遍历这个列表来检测待反序列化的类:

public Status checkInput(FilterInfo filterInfo) {   
	...       
    Class<?> clazz = filterInfo.serialClass();
    if (clazz != null) {
        ...
        if (clazz.isPrimitive())  {
            // Primitive types are undecided; let someone else decide
            return Status.UNDECIDED;
        } else {
            // Find any filter that allowed or rejected the class
            final Class<?> cl = clazz;
            // 关键代码,用stream来遍历filter的list
            Optional<Status> status = filters.stream()
                .map(f -> f.apply(cl))
                .filter(p -> p != Status.UNDECIDED)
                .findFirst();
            return status.orElse(Status.UNDECIDED);
        }
    }
    return Status.UNDECIDED;
}

<init>

Global的构造方法会根据传入的"String pattern"来创建不同的filter然后添加到上文中提到了存储filter的列表中(实际上列表中存储的是一个个Lambda表达式),官方称之为 ***"Pattern-Based Filters"***。

简单来说,这个String pattern就是一条一条的规则,规定着哪些类不可以被反序列化,哪些类可以被反序列化,这些规则如下(引自官方文档):

  • If the pattern starts with "!", the class is rejected if the rest of the pattern matches, otherwise it is accepted
  • If the pattern contains "/", the non-empty prefix up to the "/" is the module name. If the module name matches the module name of the class then the remaining pattern is matched with the class name. If there is no "/", the module name is not compared.
  • If the pattern ends with ".**" it matches any class in the package and all subpackages
  • If the pattern ends with ".*" it matches any class in the package
  • If the pattern ends with "*", it matches any class with the pattern as a prefix.
  • If the pattern is equal to the class name, it matches.
  • Otherwise, the status is undecided.

createrFilter

接上文的Global#createrFilter方法,这个方法就是传入一个规则,然后初始化了一个Global对象:

static ObjectInputFilter createFilter(String pattern, boolean checkComponentType) {
    Global filter = new Global(pattern, checkComponentType);
    return filter.isEmpty() ? null : filter;
}

小结

小结一下每个类的主要作用:

  • ObjectInputFilter是filter要实现的接口,同时也是一个函数接口(意味着可以传入一个方法引用),其checkInput()方法规定着反序列化check的具体实现。
  • Config类可以看作是一个“配置类”,规定着filter如何初始化,如何为一个ObjectInputStream设置(获取)serialFilter
  • Global类是JEP290规则的具体实现,它可以把一个个的String pattern转化成相应的filter;同时这个类本身也可以作为filter存在。

所以再回过头来看在Global类的静态代码块中所提到的那个常量jdk.serialFilter,这个常量其实就是一个属性名,Java会获取这个属性名(key)所对应的value,然后以这个value作为"String pattern",来创建一个filter(Global对象)。

A process-wide filter is configured via a system property or a configuration file. The system property, if supplied, supersedes the security property value.
  • *System property jdk.serialFilter
  • *Security property jdk.serialFilter in conf/security/java.properties

两种过滤模式

两种过滤模式:

  • 全局过滤
  • 局部过滤

全局过滤

全局过滤是指,在ObjectInputStream的创建过程中,通过ObjectInputFilter.Config这个内部类来为serialFilter赋值,进而所有ObjectInputStream对象在创建的时候就完成了serialFilter字段的初始化工作。

public ObjectInputStream(InputStream in) throws IOException {
    verifySubclass();
    bin = new BlockDataInputStream(in);
    handles = new HandleTable(10);
    vlist = new ValidationList();
    // 从Config中获取serialFilter的值
    serialFilter = ObjectInputFilter.Config.getSerialFilter();
    enableOverride = false;
    readStreamHeader();
    bin.setBlockDataMode(true);
}
// ObjectInputFilter.Config#gerSerialFilter

public static ObjectInputFilter getSerialFilter() {
    synchronized (serialFilterLock) {
        return serialFilter;
    }
}

局部过滤

局部过滤是指,在ObjectInputStream的创建过程中不初始化serialFilter字段,而是在需要的时候对单个ObjectInputStream对象进行单独设置。

private final void setInternalObjectInputFilter(ObjectInputFilter filter) {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        sm.checkPermission(new SerializablePermission("serialFilter"));
    }
    // Allow replacement of the process-wide filter if not already set
    if (serialFilter != null &&
        serialFilter != ObjectInputFilter.Config.getSerialFilter()) {
        throw new IllegalStateException("filter can not be set more than once");
    }
    if (totalObjectRefs > 0 && !Caches.SET_FILTER_AFTER_READ) {
        throw new IllegalStateException(
            "filter can not be set after an object has been read");
    }
    this.serialFilter = filter;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaSE 栈和队列

目录 1 栈 Stack1.1 概念1.2 实现1.3 Stack常见方法的使用1.4 前、中、后缀表达式 2 队列 Queue2.1 概念2.2 实现2.3 循环队列2.4 双端队列 3 Java中的栈和队列4 练习题4.1 括号匹配问题4.2 用队列实现栈4.3 用栈实现队列4.4 实现一个最小栈4.5 设计循环队列 1 栈 Stack 1.1 概…

LIMS实验室信息管理系统源码 基于计算机的数据处理技术、数据存储技术、网络传输技术、自动化仪器分析技术于一体

LIMS 是一个集现代化管理思想与基于计算机的数据处理技术、数据存储技术、网络传输技术、自动化仪器分析技术于一体&#xff0c;以实验室业务和管理工作为核心&#xff0c;遵循实验室管理国际规范&#xff0c;实现对实验室全方位管理的信息管理系统。 LIMS将样品管理、数据管理…

前端利用策略模式优化if else

策略模式 策略模式定义了一系列算法,并将每种算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。 策略模式优化if else 策略模式可以用来代替多重if else语句。 Vue中使用策略模式 我们以一个表单验证的例子来看看如何使用策略模式优化if else。 methods:…

一文让你搞懂async/await存在时的执行顺序

最近在写项目&#xff0c;发现代码中总出现这样的内容&#xff0c;一直百思不得其解&#xff0c;后来同事说这段代码的意义是把后边的任务变成宏任务执行&#xff0c;这我更迷惑了&#xff0c;我发现自己的Promise基础还是很差&#xff0c;因此在摸索了几天后&#xff0c;感觉好…

SAP ABAP内部单位外部单位转换问题

之前没有留意&#xff0c;用户用了那么久也没有发现&#xff0c;今天用户找过来说他在前台维护的是PC&#xff0c;但是报表里面显示是ST。 看了一下原来这里的“内部度量单位”就是内部的、与语言无关的计量单位格式&#xff08;ST&#xff09;。该内部格式在输出到屏幕之前&a…

完整指南:如何使用 Node.js 复制文件

文件拷贝指的是将一个文件的数据复制到另一个文件中&#xff0c;使目标文件与源文件内容一致。Node.js 提供了文件系统模块 fs&#xff0c;通过该模块可以访问文件系统&#xff0c;实现文件操作&#xff0c;包括拷贝文件。 Node.js 中文件拷贝方法 在 Node.js 中&#xff0c;有…

竞赛选题 大数据商城人流数据分析与可视化 - python 大数据分析

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于大数据的基站数据分析与可视化 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度…

Postgresql源码(114)视图权限授予逻辑

0 速查 被授权的对象在系统表中记录授权信息&#xff0c;例如pg_namespace中的nspacl列&#xff1a; {mingjieUC/mingjie,UC/mingjie,pusr1UC/mingjie}pusr1UC/mingjie的含义&#xff1a; mingjie是赋予者pusr1是被赋予者UC是权限&#xff0c;表示USAGE和CREATE 1 视图权限…

@SpringBootApplication注解的理解——如何排除自动装配 分布式情况下如何自动加载 nacos是怎么被发现的

前言 spring作为主流的 Java Web 开发的开源框架&#xff0c;是Java 世界最为成功的框架&#xff0c;持续不断深入认识spring框架是Java程序员不变的追求。 本篇博客介绍SpringBootApplicant注解的自动加载相关内容 其他相关的Spring博客文章列表如下&#xff1a; Spring基…

ubuntu20.04 jammy 安装ros2

ubunut22.04 jammy&#xff08;5.15&#xff09; ros2版本: humble 安装参考&#xff1a; Ubuntu (Debian packages) — ROS 2 Documentation: Humble documentationl 按照官方给的操作指南进行操作即可&#xff0c;到安装软件包的时候&#xff0c;若只为开发&#xff0…

C++中实现雪花算法来在秒级以及毫秒及时间内生成唯一id

1、雪花算法原理 雪花算法&#xff08;Snowflake Algorithm&#xff09;是一种用于生成唯一ID的算法&#xff0c;通常用于分布式系统中&#xff0c;以确保生成的ID在整个分布式系统中具有唯一性。它的名称来源于雪花的形状&#xff0c;因为生成的ID通常是64位的整数&#xff0…

【小白专属02】SpringBoot集成MybatisPlus

目录 前言 一、添加依赖项 二、配置数据库连接信息 三、数据库创建表 四、创建实体表 五、编写Mapper接口 六、功能测试 前言 上节回顾 上一节我们对SpringBoot框架进行了搭建&#xff0c;其实按照流程走问题不大。最主要的部分我们把下载SpringBoot demo的网址换成了…

编程每日一练(多语言实现)基础篇:百元买百鸡

文章目录 一、实例描述二、技术要点三、代码实现3.1 C 语言实现3.2 Python 语言实现3.3 Java 语言实现3.4 JavaScript 语言实现 一、实例描述 中国古代数学家张丘建在他的 《算经》 中提出了一个著名的 "百钱买百鸡问题"&#xff0c; 鸡翁一&#xff0c;值钱五&…

重新定义旅行,AnyGo for Mac让你畅享虚拟GPS位置的无限可能!

旅行是一种令人兴奋和激动人心的体验&#xff0c;而现在有了AnyGo for Mac这款强大的虚拟GPS位置工具&#xff0c;你将能够重新定义旅行&#xff0c;尽情探索全新的地理环境和体验&#xff01; AnyGo for Mac为你带来了全新的旅行方式。无需离开家门&#xff0c;你就可以通过模…

基于php的物流信息公共平台设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于php的物流信息公共平…

面对海量数据挑战,企业怎样进行数据处理?

海量数据给企业带来机遇的同时&#xff0c;也给企业带来了一定的挑战。怎样高效处理海量数据也是成为了企业面临的重要问题。 一&#xff1a;数据采集 数据采集是数据处理的第一步。企业需要进行数据采集&#xff0c;但是要保证数据的准确性以及安全性。同时需要注意&#xf…

PgSQL-向量数据库插件-lantern

PgSQL-向量数据库插件-lantern 即pgvector、pg_embedding 后又一向量数据库扩展Lantern问世了。当然也为向量列提供了hnsw索引以加速ORDER BY... LIMIT查询。Lantern使用usearch实现hnsw。 使用方法 保留了标准PgSQL接口&#xff0c;兼容其生态工具。首先需要安装该插件&#x…

服务器基础知识:raid卡有什么优势?

当今直播电商、短视频呈现热火朝天的趋势&#xff0c;是近两年的商业热门议题&#xff0c;以淘宝天猫、拼多多、抖音、小红书、视频号为代表的平台数据量呈现爆炸性的增长。据IDC预测&#xff0c;2025年全球数据总量将增至175ZB&#xff08;1ZB1万亿GB&#xff09;&#xff0c;…

数字电视码流分析仪通用规范

声明 本文是学习GB-T 26274-2010 数字电视码流分析仪通用规范. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了数字电视码流分析仪(以下简称码流分析仪)的技术要求、试验方法、检验规则及标 志、包装、运输、贮存等。 本标准适…

C++代码示例:组合数简单生成工具

文章目录 前言代码仓库内容代码&#xff08;有详细注释&#xff09;编译和运行命令结果总结参考资料作者的话 前言 C代码示例&#xff1a;组合数简单生成工具。 代码仓库 yezhening/Programming-examples: 编程实例 (github.com)Programming-examples: 编程实例 (gitee.com) …