JDK 8 - SerializedLambda

SerializedLambda是Java提供的关于lambda表达式的序列化方案,会将实现了Serializable接口的lambda表达式转换成 SerializedLambda 对象之后再去做序列化。其核心在于Java在对lambda表达式序列化时,虚拟机会添加一个writeReplace()方法。
根据Java的序列化机制,虚拟机在调用write(obj)序列化对象前,如果被序列化对象有writeReplace方法,则会先调用该方法,用该方法返回的对象进行序列化,即序列化对象被替换了。
同理,lambda表达式在序列化前也会调用writeReplace(),然后返回一个SerializedLambda 对象(真正的被序列化的对象),该对象包含了lambda表达式的所有信息,比如函数名implMethodName、函数签名implMethodSignature等,这些信息都是以字段形式存在的,这样就解决了lambda序列化的问题。
既然被序列化的对象有writeReplace()方法,那么我们也可以直接调用该方法获取相应的SerializedLambda对象,有了SerializedLambda对象一切就迎刃而解了。

interface NamedFunction<T, R> extends Function<T, R>, TypedName<R>, Serializable {
    R apply(T t);

    @Override
    @SneakyThrows
    default Class<R> type() {
        //调用writeReplace()方法,返回一个SerializedLambda对象
        SerializedLambda lambda = this.lambda();
        sun.reflect.generics.parser.SignatureParser parser = SignatureParser.make();
        MethodTypeSignature methodSig = parser.parseMethodSig(lambda.getImplMethodSignature());
        ClassTypeSignature signature = (ClassTypeSignature) methodSig.getReturnType();
        return (Class<R>) Class.forName(signature.getPath().get(0).getName());
    }

    @SneakyThrows
    default String name() {
        SerializedLambda lambda = lambda();
        return lambda.getImplMethodName();
    }

    @SneakyThrows
    default SerializedLambda lambda() {
        Method method = this.getClass().getDeclaredMethod("writeReplace");
        method.setAccessible(Boolean.TRUE);
        //调用writeReplace()方法,返回一个SerializedLambda对象
        return (SerializedLambda) method.invoke(this);
    }
}

其它

  1. JDK中Lambda表达式的序列化与SerializedLambda的巧妙使用

SerializedLambda 类上的注释有四大段
段落一:SerializedLambda是Lambda表达式的序列化形式,这类存储了Lambda表达式的运行时信息。
段落二:编译器需确保生成的 lambda 类的实例会提供一个writeReplace 方法,且该方法会返回一个SerializedLambda实例。
段落三:SerializedLambda提供了readResolve方法,其职能为调用 capturingClass 的静态方法$deserializeLambda$(SerializedLambda)并且把自身实例作为入参。capturingClass 即为 lambda 表达式定义所在的类。
段落四: 序列化和反序列化产生的函数对象的身份敏感操作的标识形式(如System.identityHashCode()、对象锁定等等)是不可预测的。

  1. Serialize a Lambda in Java

When the JVM encounters a lambda expression, it will use the built-in ASM to build an inner class. So, what does this inner class look like? We can dump this generated inner class by specifying the jdk.internal.lambda.dumpProxyClasses property on the command line:

-Djdk.internal.lambda.dumpProxyClasses=<dump directory>

After dumping, we can inspect this generated inner class with an appropriate Java decompiler:
JRE 导出的 lambda 生成的类
inspecting the compiled class file, we also need to inspect the newly generated inner class. NotSerializableLambdaExpression.lambda$getLambdaExpressionObject$0 method, which is generated by the Java compiler and represents our lambda expression implementation.

for serializable lambda expression Runnable r = (Runnable & Serializable) () -> System.out.println(“please serialize this message”);
导出的实现了Serializable 接口的 labmda 表达式的实际内部类
In generallambda 序列化流程图
For tips, The main responsibility of the above $deserializeLambda$ method is to construct an object. First, it checks the SerializedLambda‘s getXXX methods with different parts of the lambda expression details. Then, if all conditions are met, it will invoke the SerializableLambdaExpression::lambda$getLambdaExpressionObject$36ab28bd$1 method reference to create an instance. Otherwise, it will throw an IllegalArgumentException. the code detail is expresed in the following picture.
在这里插入图片描述

When we use the ObjectOutputStream to serialize a lambda expression, the ObjectOutputStream will find the generated inner class contains a writeReplace method that returns a SerializedLambda instance. Then, the ObjectOutputStream will serialize this SerializedLambda instance instead of the original object. Next, when we use the ObjectInputStream to deserialize the serialized lambda file, a SerializedLambda instance is created. Then, the ObjectInputStream will use this instance to invoke the readResolve defined in the SerializedLambda class. And, the readResolve method will invoke the $deserializeLambda$ method defined in the capturing class. Finally, we get the deserialized lambda expression.

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

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

相关文章

mac docker desktop被禁用了,如何使用虚拟机lima运行docker

安装lima brew install lima创建配置 echo "\\ndynamic:\n big-sur:\n image: docker://docker:git\n linux:\n image: docker.io/limasoftware/ubuntu:20.04 \\n" > ~/.lima/default.yaml启动名叫default的虚拟机 limactl start default测试 limactl …

echarts多个折线图共用X轴,实现tooltip合并和分离

echarts共享X轴案例&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Document</…

【办公类-23-01】20240128《百家姓》单姓与复姓

结果展示 背景需求&#xff1a; 20240128我去了苏州吴江的黎里古镇游玩&#xff0c;哪里有一面墙上都是百家姓做装饰。 这让我又想到我班级里的7个王姓的重姓率&#xff01; 【办公类-19-02-01】20240119统计班级幼儿姓名的长度、汉字重复、拼音重复&#xff08;有无声调&…

【ArcGIS遇上Python】python实现批量XY坐标生成shp点数据文件

单个手动生成:【ArcGIS风暴】ArcGIS 10.2导入Excel数据X、Y坐标(经纬度、平面坐标),生成Shapefile点数据图层 文章目录 一、问题分析二、解决办法三、注意事项一、问题分析 现有多个excel、txt或者csv格式的坐标数据,需要根据其坐标批量一键生成shp点数据,如下X为经度,…

回归预测 | MATLAB实现PSO-GRNN粒子群优化广义回归神经网络多输入单输出预测(含优化前后预测可视化)

回归预测 | MATLAB实现PSO-GRNN粒子群优化广义回归神经网络多输入单输出预测 目录 回归预测 | MATLAB实现PSO-GRNN粒子群优化广义回归神经网络多输入单输出预测预测效果基本介绍程序设计参考资料预测效果 <

力扣3. 无重复字符的最长子串(滑动窗口)

Problem: 3. 无重复字符的最长子串 文章目录 题目描述思路及解法复杂度Code 题目描述 思路及解法 由于题目要求求出字符串中最长的连续无重复字符的最长子串&#xff0c;所以利用这个特性我们可以比较容易的想到利用双指针中的滑动窗口技巧来解决&#xff0c;但在实际的求解中…

【学网攻】 第(14)节 -- 动态路由(EIGRP)

系列文章目录 目录 系列文章目录 文章目录 前言 一、动态路由EIGRP是什么&#xff1f; 二、实验 1.引入 实验步骤 实验拓扑图 实验配置 看到D开头是便是我们的EIGRP动态路由 总结 文章目录 【学网攻】 第(1)节 -- 认识网络【学网攻】 第(2)节 -- 交换机认识及使用【学…

微信小程序(二十二)获取全局实例

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.全局实例的定义位置 2.全局实例中数据的修改方法 源码&#xff1a; app.js App({//数据可以包括在第二级globalData:{userInfo:null,token:1243,userInfo:null},//globalData并不是关键词&#xff0c;数据可以…

WSL2 Debian系统添加支持SocketCAN

本人最近在使用WSL2&#xff0c;Linux系统选择的是Debian&#xff0c;用起来很不错&#xff0c;感觉可以代替VMware Player虚拟机。 但是WSL2 Debian默认不支持SocketCAN&#xff0c;这就有点坑了&#xff0c;由于本人经常要使用SocketCAN功能&#xff0c;所以决定让Debian支持…

菜谱的未来:SpringBoot, Vue与MySQL的智能推荐系统设计

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

[Python-贪心算法]

135. 分发糖果 n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 你需要按照以下要求&#xff0c;给这些孩子分发糖果&#xff1a; 每个孩子至少分配到 1 个糖果。 相邻两个孩子评分更高的孩子会获得更多的糖果。 请你给每个孩子分发糖果&#xff0c;计算…

Redis 面试题 | 18.精选Redis高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

数学知识第四期 快速幂

前言 快速幂在算法比赛中十分的重要&#xff0c;而且代码简短&#xff0c;清楚易懂&#xff0c;大家应该熟练掌握&#xff01;&#xff01;&#xff01; 一、什么是快速幂&#xff1f; 快速幂是一种高效的算法&#xff0c;用于计算某个数的n次幂。它的基本思想是将原式转换为…

JavaScript DOM属性和方法之element元素对象

在HTML DOM中&#xff0c;elment对象表示HTML与纳素&#xff0c;可以包含的节点类型有元素u节点、文本节点、注释节点。它们有响应的属性和方法&#xff0c;有很多都是我们之前用过的。 一、element对象属性 1、attributes 2、childNodes 3、className 4、clientWidth、of…

【大厂AI课学习笔记】1.1.4 学科和学习路径

一、8大学科 特点是特点 &#xff1a;厚基础、重交叉、宽口径。 八大学科分别是&#xff1a;数学与统计、科学与工程、计算机科学与技术、人工智能核心、认知与神经科学、先进机器人技术、人工智能工具与平台。 每个学科&#xff0c;又向下延伸。 MORE: AI&#xff0c;即人…

【DDD】学习笔记-限界上下文的控制力

引入限界上下文的目的&#xff0c;不在于如何划分&#xff0c;而在于如何控制边界。因此&#xff0c;我们就需要将对限界上下文的关注转移到对控制边界的理解。显然&#xff0c;对应于统一语言&#xff0c;限界上下文是语言的边界&#xff0c;对于领域模型&#xff0c;限界上下…

muduo网络库剖析——事件循环线程池EventLoopThreadPool类

muduo网络库剖析——线程Thread类 前情从muduo到my_muduo 概要框架与细节成员函数使用方法 源码结尾 前情 从muduo到my_muduo 作为一个宏大的、功能健全的muduo库&#xff0c;考虑的肯定是众多情况是否可以高效满足&#xff1b;而作为学习者&#xff0c;我们需要抽取其中的精…

Spring结合工厂模式

学习设计模式&#xff0c;不要进入一个误区生搬硬套&#xff0c;它是一种编程思想&#xff0c;结合实际使用&#xff0c;往往设计模式是混合使用的 工厂模式 核心本质&#xff1a;使用工厂统一管理对象的创建&#xff0c;将调用者跟实现类解耦 我这里使用Spring容器的支持&am…

latent-diffusion model环境配置--我转载的

latent-diffusion model环境配置&#xff0c;这可能是你能够找到的最细的博客了_latent diffusion model 训练 autoencoder-CSDN博客 前言 最近在研究diffusion模型&#xff0c;并对目前最火的stable-diffusion模型很感兴趣&#xff0c;又因为stable-diffusion是一种latent-di…

【QT+QGIS跨平台编译】之十五:【libTiff+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、libTiff介绍二、文件下载三、文件分析四、pro文件五、编译实践一、libTiff介绍 libTiff是一个用于处理TIFF图像文件格式的开源软件库。 TIFF(Tagged Image File Format)是一种灵活且广泛支持的图像文件格式,常用于存储照片和其他高质量图像。libTiff提供了一套…