Java

深入理解 Java 代码块

深入理解 Java 代码块

D瓜哥
在 Java 虚拟机操作码探秘:常量指令 中对 Java 虚拟机操作码中关于常量操作的指令(操作码)做了初步介绍。估计会有人疑问:文中的“栈”、“栈顶”等是什么?接下来就准备解答这些疑问。 在答疑解惑之前,先来了解一下 Java 编译器对 Java 代码中的代码块是如何处理的?常见的代码块有普通代码块和静态代码块,下面对其做分别介绍。由于涉及到构造函数,所以,先对构造函数做一个介绍。 构造函数 无构造函数 先来看看当没有声明构造函数时,编译结果是什么样的: /** * 无构造函数示例 * * @author D瓜哥 · https://www.diguage.com */ public class Example { } 编译后,使用 javap -c 查看一下编译结果: $ javap -c Example Compiled from "Example.java" public class Example { public Example(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return } 从结果上来看:编译器自动给没有声明构造函数的类,生成了一个无参构造函数,并且在其中调用了父类(这里是 Object)的无参构造函数。这是大家都熟知的基础知识。 有参构造函数 再来看看当有声明参数的构造函数时,编译结果是什么样的: /** * 有参构造函数示例 * * @author D瓜哥 · https://www.
Java 虚拟机操作码探秘:常量指令

Java 虚拟机操作码探秘:常量指令

D瓜哥
在 Java 虚拟机指令(操作码)集 中给出了一个操作码的列表。针对所有的指令,仅仅给出了一个大概介绍,对理解来说可以说毫无助力。为了弥补这个短板,这里也学习 “Hessian 协议解释与实战”系列 那样,来一个详细解释和实战,配合实例来做个深入分析和讲解。这是这个系列的第一篇文章,就以列表中第一部分“常量”指令开始。 从 Java 虚拟机指令(操作码)集 列表上来看,一共 21 个指令;按照处理数据的类型,合并同类项后,剩下有 nop、 aconst_null、 iconst_<i>、 lconst_<l>、 fconst_<f>、 dconst_<d>、 bipush、 sipush、 ldc 和 ldc2_w 等几个指令。下面,按照顺序,对其进行一一讲解。 操作码助记符的首字母一般是有特殊含义的,表示操作码所作用的数据类型: i 代表对 int 类型的数据操作; l 代表 long; s 代表 short; b 代表 byte;c 代表 char;f 代表 float, d 代表 double; a 代表 reference。 尖括号之间的字母指定了指令隐含操作数的数据类型,<n> 代表非负的整数; <i> 代表是 int 类型数据; <l> 代表 long 类型; <f> 代表 float 类型; <d> 代表 double 类型。 另外还需要指出一点:这种指令表示法在整个 Java 虚拟机规范之中都是通用的。
制定组织内 Maven BOM 的一些规范

制定组织内 Maven BOM 的一些规范

D瓜哥
在 关于升级 Spring 等依赖的一些经验 中介绍了 D瓜哥在升级项目依赖时,遇到的一些问题以及一些需要注意的地方。但是,这里还存在一个问题:各个依赖的版本依然散落在各个项目中;升级依赖,需要在所有项目中,把所有相关项目的依赖都巴拉一下,费时费力。解决这个问题的一个比较好的办法是制定一个组织内部的 Maven BOM,集中管理相关依赖的版本。这样升级的时候,还需要修改 BOM 的版本号即可。 Maven BOM 介绍 BOM(Bill of Materials)是由 Maven 提供的功能,它通过定义一整套相互兼容的 jar 包版本集合,使用时只需要依赖该BOM文件,即可放心的使用需要的依赖 jar 包,且无需再指定版本号。 一些基本原则 Spring & Spring Boot 是 Java 生态中,全世界广泛使用的开发框架,在各种场景中都经受过考验。所以,Spring & Spring Boot 选择的 Jar 在稳定性和兼容性方面都有保证。另外,Spring Boot 本身就集成了非常非常多的依赖,并为此创建了一个网页 Spring Boot Dependency versions 来说明它集成的依赖及版本。故而,可以选择以 Spring Boot 为底本,来制作自己的 BOM。 如果不需要 Spring 相关依赖,可以将 Spring 相关依赖删除掉,然后在其之上增加组织内部依赖而创建自己的 BOM。 如果需要 Spring 相关依赖,那么直接继承 在稳定性方面,经过更多人检验的版本,则稳定性更有保障。所以,选择最近两年下载次数比较多的版本。 更新的版本,更容易获得技术升级带来的红利。所以,在可能的情况下,优先选择高版本。 优先考虑目标 JDK 的支持情况。例如,一些依赖的高版本或低版本不支持 Java 8,但是 Java 8 是生产环境部署的主要版本,那么太高的版本和低版本都不适合。 外部 Jar 包选择标准 尽量将外部中间件统一到同一种依赖的同一个版本上。例如:数据库连接池全部使用 HikariCP;JSON 处理统一使用 Jackson。
Java 虚拟机指令(操作码)集

Java 虚拟机指令(操作码)集

D瓜哥
最近在研究 Java 虚拟机字节码。在 《Java虚拟机规范》 看到一个整理完整的 Java 虚拟机指令集(也叫操作码)列表。转载过来,方便查阅。 关于 Java 虚拟机指令(操作码),准备写一个“探秘”系列: Java 虚拟机操作码探秘:常量指令 — 重点介绍一下关于“常量”指令。 分类 操作码 助记符 指令含义 常量 0 0x00 nop 什么都不做 1 0x01 aconst_null 将 null 推送至栈顶 2 0x02 iconst_m1 将 int 类型 -1 推送至栈顶 3 0x03 iconst_0 将 int 类型 0 推送至栈顶 4 0x04 iconst_1 将 int 类型 1 推送至栈顶 5 0x05 iconst_2 将 int 类型 2 推送至栈顶 6 0x06 iconst_3 将 int 类型 3 推送至栈顶
关于升级 Spring 等依赖的一些经验

关于升级 Spring 等依赖的一些经验

D瓜哥
到公司后,熟悉了一些项目后,发现大部分项目的依赖都比较陈旧,比如某些项目还在使用 Spring 3.x 的版本。所以,在进行需求开发时,也顺手把一些项目的依赖给升级了一下。周五,一个小伙伴问我关于升级 Spring 的经验。正好趁此机会,把一些经验总结一下。 下面的描述以 Java 8 为准,没有在其他版本 Java 上试验过。参考时,请慎重。描述的原则如下: 尽量选择还在维护中的版本,而不是已经 End of Life 的过时版。这样有问题可以及时反馈并得到修复。 Java 8 是目标版本,所以,一定要兼容 Java 8。 Spring Framework 升级 Spring Framework 从 3.2.6.RELEASE 开始提供 BOM。可以利用 BOM 简化 Spring 依赖声明: <!-- D瓜哥 · https://www.diguage.com --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-framework-bom</artifactId> <version>5.3.22</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> 这样,就不需要重复声明 Spring 依赖的版本,直接使用即可。 Spring Framework Bom 保证了 Spring 自身依赖的版本统一。 这里,关于 Spring 的升级,还有几点需要说明: 从 Spring 3.0.0.RELEASE 到 Spring 3.1.4.RELEASE,Spring 有一个 spring-asm,如果不再使用这个区间的 Spring,请把这个依赖删掉。
Hessian、Msgpack 和 JSON 实例对比

Hessian、Msgpack 和 JSON 实例对比

D瓜哥
前段时间,翻译了 Hessian 2.0 的序列化协议,发布在了 Hessian 2.0 序列化协议(中文版)。但是,其中有很多言语不详之处。所以,接下来会用几篇文章来详细解释并实践一下 Hessian 序列化协议,以求做到知其然知其所以然。 目录如下: Hessian 2.0 序列化协议(中文版) — Hessian 序列化协议的中文翻译版。根据后面的“协议解释与实战”系列文章,增加了协议内容错误提示。 Hessian 协议解释与实战(一):布尔、日期、浮点数与整数 — 介绍布尔型数据、日期类型、浮点类型数据和整数类型数据等四种类型的数据的处理。 Hessian 协议解释与实战(二):长整型、二进制数据与 Null — 介绍长整数类型数据、二进制数据和 null 等三种类型的数据的处理。 Hessian 协议解释与实战(三):字符串 — 专门介绍了关于字符串的处理。由于字符串需要铺垫的基础知识比较多,处理细节也有繁琐,所以单独成篇来介绍。 Hessian 源码分析(Java) — 开始第四篇分析之前,先来介绍一下 Hessian 的源码实现。方便后续展开说明。 Hessian 协议解释与实战(四):数组与集合 — 铺垫了一些关于实例对象的处理,重点介绍关于数组和集合的相关处理。 Hessian 协议解释与实战(五):对象与映射 — 重点介绍关于对象与映射的相关处理。 Hessian、Msgpack 和 JSON 实例对比 — 用实例对比 JSON、Hessian 和 MessagePack 的区别。 未完待续,敬请继续关注 "地瓜哥"博客网。 本文用实际来对比一下 JSON、Hessian 和 MessagePack 的区别。 模型 package com.diguage; import java.math.BigDecimal; import java.util.Date; /** * 用户 * * @author D瓜哥 · https://www.
Hessian 协议解释与实战(五):对象与映射

Hessian 协议解释与实战(五):对象与映射

D瓜哥
前段时间,翻译了 Hessian 2.0 的序列化协议,发布在了 Hessian 2.0 序列化协议(中文版)。但是,其中有很多言语不详之处。所以,接下来会用几篇文章来详细解释并实践一下 Hessian 序列化协议,以求做到知其然知其所以然。目录如下: Hessian 2.0 序列化协议(中文版) — Hessian 序列化协议的中文翻译版。根据后面的“协议解释与实战”系列文章,增加了协议内容错误提示。 Hessian 协议解释与实战(一):布尔、日期、浮点数与整数 — 介绍布尔型数据、日期类型、浮点类型数据和整数类型数据等四种类型的数据的处理。 Hessian 协议解释与实战(二):长整型、二进制数据与 Null — 介绍长整数类型数据、二进制数据和 null 等三种类型的数据的处理。 Hessian 协议解释与实战(三):字符串 — 专门介绍了关于字符串的处理。由于字符串需要铺垫的基础知识比较多,处理细节也有繁琐,所以单独成篇来介绍。 Hessian 源码分析(Java) — 开始第四篇分析之前,先来介绍一下 Hessian 的源码实现。方便后续展开说明。 Hessian 协议解释与实战(四):数组与集合 — 铺垫了一些关于实例对象的处理,重点介绍关于数组和集合的相关处理。 Hessian 协议解释与实战(五):对象与映射 — 重点介绍关于对象与映射的相关处理。 Hessian、Msgpack 和 JSON 实例对比 — 用实例对比 JSON、Hessian 和 MessagePack 的区别。 Avro、ProtoBuf、Thrift 的模式演进之路 — 翻译的 Martin Kleppmann 的文章,重点对比了 Avro、ProtoBuf、Thrift 的序列化处理思路。 在上一篇文章 Hessian 协议解释与实战(四):数组与集合 中研究了数组和集合的处理方式。接下来介绍对象和映射的处理。 基础工具方法 基础工具方法就不再赘述,请直接参考 Hessian 协议解释与实战(一):基础工具方法 中提到的几个方法。
Hessian 协议解释与实战(四):数组与集合

Hessian 协议解释与实战(四):数组与集合

D瓜哥
前段时间,翻译了 Hessian 2.0 的序列化协议,发布在了 Hessian 2.0 序列化协议(中文版)。但是,其中有很多言语不详之处。所以,接下来会用几篇文章来详细解释并实践一下 Hessian 序列化协议,以求做到知其然知其所以然。目录如下: Hessian 2.0 序列化协议(中文版) — Hessian 序列化协议的中文翻译版。根据后面的“协议解释与实战”系列文章,增加了协议内容错误提示。 Hessian 协议解释与实战(一):布尔、日期、浮点数与整数 — 介绍布尔型数据、日期类型、浮点类型数据和整数类型数据等四种类型的数据的处理。 Hessian 协议解释与实战(二):长整型、二进制数据与 Null — 介绍长整数类型数据、二进制数据和 null 等三种类型的数据的处理。 Hessian 协议解释与实战(三):字符串 — 专门介绍了关于字符串的处理。由于字符串需要铺垫的基础知识比较多,处理细节也有繁琐,所以单独成篇来介绍。 Hessian 源码分析(Java) — 开始第四篇分析之前,先来介绍一下 Hessian 的源码实现。方便后续展开说明。 Hessian 协议解释与实战(四):数组与集合 — 铺垫了一些关于实例对象的处理,重点介绍关于数组和集合的相关处理。 Hessian 协议解释与实战(五):对象与映射 — 重点介绍关于对象与映射的相关处理。 Avro、ProtoBuf、Thrift 的模式演进之路 — 翻译的 Martin Kleppmann 的文章,重点对比了 Avro、ProtoBuf、Thrift 的序列化处理思路。 在上一篇文章 Hessian 源码分析(Java) 对 Hessian 的 Java 实现做了一个概要的分析,对处理流程以及整体架构做了一个简单的分析。接下来,回到主题,继续来解释 Hessian 序列化协议。这篇文章,我们来重点分析一下数组与集合相关的操作。 基础工具方法 基础工具方法就不再赘述,请直接参考 Hessian 协议解释与实战(一):基础工具方法 中提到的几个方法。 对打印字符的工具做一下改造:
Hessian 源码分析(Java)

Hessian 源码分析(Java)

D瓜哥
前面通过几篇文章,解释并实践了一下 Hessian 的序列化协议。文章目录如下: Hessian 2.0 序列化协议(中文版) — Hessian 序列化协议的中文翻译版。根据后面的“协议解释与实战”系列文章,增加了协议内容错误提示。 Hessian 协议解释与实战(一):布尔、日期、浮点数与整数 — 介绍布尔型数据、日期类型、浮点类型数据和整数类型数据等四种类型的数据的处理。 Hessian 协议解释与实战(二):长整型、二进制数据与 Null — 介绍长整数类型数据、二进制数据和 null 等三种类型的数据的处理。 Hessian 协议解释与实战(三):字符串 — 专门介绍了关于字符串的处理。由于字符串需要铺垫的基础知识比较多,处理细节也有繁琐,所以单独成篇来介绍。 Hessian 源码分析(Java) — 开始第四篇分析之前,先来介绍一下 Hessian 的源码实现。方便后续展开说明。 Hessian 协议解释与实战(四):数组与集合 — 铺垫了一些关于实例对象的处理,重点介绍关于数组和集合的相关处理。 Hessian 协议解释与实战(五):对象与映射 — 重点介绍关于对象与映射的相关处理。 Hessian、Msgpack 和 JSON 实例对比 — 用实例对比 JSON、Hessian 和 MessagePack 的区别。 Avro、ProtoBuf、Thrift 的模式演进之路 — 翻译的 Martin Kleppmann 的文章,重点对比了 Avro、ProtoBuf、Thrift 的序列化处理思路。 该系列第四篇文章准备详细介绍一下 Hessian 对对象、链表以及 Map 等处理。但是,越调试代码,越发觉得应该先对 Hessian 的实现做一个源码分析。于是,就有了本文。 这里有几点需要声明一下: 在上面“解释与实战”系列文章中提到的代码就不再重复说明。 通过“解释与实战”系列文章,大家应该可以领略到,处理序列化有大量的细节。但是,本文并不打算涉及。本文重点是介绍 Hessian 的 Java 实现的架构蓝图。相当于给指明一条路,沿着这条路,大家就可以探索 Hessian 的各种细节。
Hessian 协议解释与实战(三):字符串

Hessian 协议解释与实战(三):字符串

D瓜哥
前段时间,翻译了 Hessian 2.0 的序列化协议,发布在了 Hessian 2.0 序列化协议(中文版)。但是,其中有很多言语不详之处。所以,接下来会用几篇文章来详细解释并实践一下 Hessian 序列化协议,以求做到知其然知其所以然。目录如下: Hessian 2.0 序列化协议(中文版) — Hessian 序列化协议的中文翻译版。根据后面的“协议解释与实战”系列文章,增加了协议内容错误提示。 Hessian 协议解释与实战(一):布尔、日期、浮点数与整数 — 介绍布尔型数据、日期类型、浮点类型数据和整数类型数据等四种类型的数据的处理。 Hessian 协议解释与实战(二):长整型、二进制数据与 Null — 介绍长整数类型数据、二进制数据和 null 等三种类型的数据的处理。 Hessian 协议解释与实战(三):字符串 — 专门介绍了关于字符串的处理。由于字符串需要铺垫的基础知识比较多,处理细节也有繁琐,所以单独成篇来介绍。 Hessian 源码分析(Java) — 开始第四篇分析之前,先来介绍一下 Hessian 的源码实现。方便后续展开说明。 Hessian 协议解释与实战(四):数组与集合 — 铺垫了一些关于实例对象的处理,重点介绍关于数组和集合的相关处理。 Hessian 协议解释与实战(五):对象与映射 — 重点介绍关于对象与映射的相关处理。 Hessian、Msgpack 和 JSON 实例对比 — 用实例对比 JSON、Hessian 和 MessagePack 的区别。 Avro、ProtoBuf、Thrift 的模式演进之路 — 翻译的 Martin Kleppmann 的文章,重点对比了 Avro、ProtoBuf、Thrift 的序列化处理思路。 在上一篇文章 Hessian 协议解释与实战(二):长整型、二进制数据与 Null 中研究了长整型、二进制数据与 null 等三种数据类型的处理方式。接下来,我们再来介绍字符串的处理情况。