Java将引入新的对象类型来解决内存利用问题
2022年Java将有什么新的特性和改进,我相信很多Java开发者都想知道。结合Java语言架构师布莱恩·格茨(Brian Goetz)最近的一些分享,胖哥给大家爆个料。老规矩,点赞走起。
Valhalla
布莱恩·格茨在去年底发表了一篇名为State of Valhalla的文章,里面信息量非常大,里面提到早在2014年Java项目组就启动了一个名叫Valhalla的项目,这个项目将为JVM平台带来更加灵活的、扁平化的数据类型。在2021年该项目将有进一步的动作,值对象(value objects)、原始类(primitive classes)、专用泛型(specialized generics)即将引入JVM平台。今天先来聊聊这个值对象是个啥。
我们知道什么是“值”,什么是“对象”,但是什么是“值对象”呢?不光你们懵逼,我也懵逼,来一起研究研究。
Java类型系统的不足

Java类型系统由内置的10种类型组成,这10种类型无法直接表达复杂的数据结构,例如字符串、三维坐标、空间向量等等,但是开发者可以用这10种类型来为业务实体建模,Java的类型体系是非常有用的。
但是Java类型仍然存在“缺陷”, 同一个类的两个对象包含完全相同的属性,但是它们的内存寻址是不一样的。

所以从某种意义上说,他们有自己的身份标识。
但是对于原始类型就不一样了,如果一个int类型的变量值为7,另一个也为7,区分它们有意义吗?这个7还是那个7?显然是无意义的。
让我们再来举一个现实中的例子,两件相同尺寸、材质的红色衣服肯定是两件不同的衣服,但是它们的材质肯定是一种材质,颜色肯定是一种颜色,不会有傻子认为这是两种颜色。这里面的尺寸当然可以通过Java中的原始类型去描述,但是材质和颜色不行(虽然颜色可以用十六进制表示),这里的尺寸、材质、颜色都应该被认为是原语。
这个痛点促使了Valhalla项目的诞生。
对象头
为了理解Valhalla引入的 Value Object / Class 和 Primitive Object / Class 概念能够给我们带来了什么,我们需要看看JVM是如何将对象保存在内存中的。

对象头对类的对象非常重要,决定哪个线程可以访问对象、垃圾收集器标记、对象hash;更重要的还有对象的类型指针,它能够在运行时动态访问对象的类,并从其类到该对象的详细信息,比如继承多态、反射。
但是凡事都有两面性,Java对象内存占用的大小取决于它所包含的信息的总和,对象头在 64 位系统上至少需要 16 个字节,在 32 位系统上至少需要 8 个字节(当然JVM可以通过配置项去设置如何保存对象头)。很多对象不需要多线程,也不需要什么对象标识,就像上面提到的衣服的颜色,只有颜色的值才是我们关心的事。这种冗余的内存占用让Java为人诟病。
Value Class
对于许多对象来说,它属性值的相等性是我们关心的,其它类信息没什么用,而且只为保存值和对这些值进行操作而编写的类在所有类中所占的比例非常大。Valhalla项目为这样的场景引入了一个新的类类型:Value Class。目前还只是JEP草案,但是已经初具形态:
value class Substring implements CharSequence {
private String str;
private int start;
private int end;
public Substring(String str, int start, int end) {
checkBounds(start, end, str.length());
this.str = str;
this.start = start;
this.end = end;
}
public int length() {
return end - start;
}
public char charAt(int i) {
checkBounds(0, i, length());
return str.charAt(start + i);
}
public Substring subSequence(int s, int e) {
checkBounds(s, e, length());
return new Substring(str, start + s, start + e);
}
public String toString() {
return str.substring(start, end);
}
private static void checkBounds(int start, int end, int length) {
if (start < 0 || end < start || length < end)
throw new IndexOutOfBoundsException();
}
}
Value Class和我们常见的类差不多,但是它可能(这里依然在讨论中)具有下面一些特性:
值对象是没有身份的对象,通常情况下我们用
==运算符检查身份,这里可能和equals()不再有区别。值类本身和它的所有字段默认都是
final的。该类不直接或间接地实现
java.lang.IdentityObject(有身份标识类的新超类)。这意味着超类要么是无状态抽象类,要么Object是无状态抽象类。值类都是
java.lang.ValueObject的隐式实现。没有构造
super函数调用构造函数。将在不执行任何超类初始化代码的情况下创建实例。无法在值类中使用
synchronized关键字。(可能)该类没有声明
finalize()方法。(可能)构造函数不使用
this来设置构造函数主体中的字段,或者可能在所有字段都明确内存分配之后。
其它的操作和普通的类应该差别不大,但是要注意的是,JDK标准库中的一些原有类如果被认定为Value Class需要做兼容性处理。
value要成为保留字还是关键字?
这不是全部
Value Class对Java类对象头进行了阉割,有利于降低Java的内存消耗,但是这不是Valhalla计划的全部。对于这一部分过于超前的内容,我写起来其实是很有困难的,构思了好几天,从场景出发来了解一门编程语言的设计有利于从根本提高自己。如果你想了解更多关于Valhalla的东西,可以关注我,我会继续分享相关的知识。
关注公众号:Felordcn 获取更多资讯
Java将引入新的对象类型来解决内存利用问题的更多相关文章
- SAP CRM 用户界面对象类型和设计对象
在CRM中的用户界面对象类型的帮助下,我们可以做这些工作: 进行不同的视图配置 创建动态导航 从设计层控制字段标签.值帮助 控制BOL对象的属性的可视性 从导航栏访问自定义组件 一个用户界面对象类型之 ...
- Spring实战(十)Spring AOP应用——为方法引入新功能、为对象引入新方法
切面最基本的元素是通知和切点,切点用于准确定位应该在什么地方应用切面的通知. 1.Spring借助AspectJ的切点表达式语言来定义Spring切面 在Spring中,要使用AspectJ的切点表达 ...
- JAVA IO分析二:字节数组流、基本数据&对象类型的数据流、打印流
上一节,我们分析了常见的节点流(FileInputStream/FileOutputStream FileReader/FileWrite)和常见的处理流(BufferedInputStream/B ...
- Java中引用类型变量,对象,值类型,值传递,引用传递 区别与定义
一.Java中什么叫做引用类型变量?引用:就是按内存地址查询 比如:String s = new String();这个其实是在栈内存里分配一块内存空间为s,在堆内存里new了一个Stri ...
- [原创]java WEB学习笔记81:Hibernate学习之路--- 对象关系映射文件(.hbm.xml):hibernate-mapping 节点,class节点,id节点(主键生成策略),property节点,在hibernate 中 java类型 与sql类型之间的对应关系,Java 时间和日期类型的映射,Java 大对象类型 的 映射 (了解),映射组成关系
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- 2016年11月3日JS脚本简介数据类型: 1.整型:int 2.小数类型: float(单精度) double(双精度) decimal () 3.字符类型: chr 4.字符串类型:sting 5.日期时间:datetime 6.布尔型数据:bool 7.对象类型:object 8.二进制:binary 语言类型: 1.强类型语言:c++ c c# java 2.弱类型语
数据类型: 1.整型:int 2.小数类型: float(单精度) double(双精度) decimal () 3.字符类型: chr 4.字符串类型:sting 5.日期时间:datetime 6 ...
- python与java的内存机制不一样;java的方法会进入方法区直到对象消失 方法才会消失;python的方法是对象每次调用都会创建新的对象 内存地址都不i一样
python与java的内存机制不一样;java的方法会进入方法区直到对象消失 方法才会消失;python的方法是对象每次调用都会创建新的对象 内存地址都不i一样
- objective-c和java下解析对象类型和数组类型JSON字符串
首先讲objective-c如何实现: 这里需要用到2个插件,一个是JSONKit,另一个是Jastor,一共包含6个文件,3个.h头文件和3个.m实现文件.在ARC的工程中如何导入不支持ARC的第三 ...
- Java 基本类型和对象类型的区别
Java 基本类型和对象类型的区别 基本类型: int long byte float double char boolean short 对象类型: Integer Long Byte Float ...
随机推荐
- Linux 三剑客之grep
目录 Linux 三剑客之grep 搭配命令-find 三剑客之grep: 正则表达式: Linux 三剑客之grep 搭配命令-find find命令是根据文件的名称或者属性查找文件,并不会显示文件 ...
- Sublime Text3 Package Control Emmet插件安装
https://www.cnblogs.com/carrie-hong/p/4995735.html https://www.cnblogs.com/tamato-jacob-wealllostcon ...
- javascript中的12种循环遍历方法
1.for (自定义条件) 循环 let arr = [1,2,3]; for(let i =0;i<arr.length;i++){ console.log(i,arr[i]) } 2.for ...
- Java 中的5个代码性能提升技巧,最高提升近10倍
文章持续更新,可以关注公众号程序猿阿朗或访问未读代码博客. 本文 Github.com/niumoo/JavaNotes 已经收录,欢迎Star. 这篇文章介绍几个 Java 开发中可以进行性能优化的 ...
- Spring整合redis实现key过期事件监听
打开redis服务的配置文件 添加notify-keyspace-events Ex 如果是注释了,就取消注释 这个是在以下基础上进行添加的 Spring整合redis:https://www. ...
- SpringBoot整合redis实现过期key监听事件
Spring整合redis实现key过期事件监听:https://www.cnblogs.com/pxblog/p/13969375.html 可以用于简单的过期订单取消支付.7天自动收货场景中 1. ...
- Java用sort实现对数组的降序排序
在调用Arrays.sort()对数组进行排序时,默认是升序排序的,如果想让数组降序排序,有下面两种方法: 利用Collections的reverseOrder import java.util.*; ...
- @Transactional 失效
1.Transactional注解标注方法修饰符为非public时,@Transactional注解将会不起作用. @Transactional void insertTestWrongModi ...
- 「HAOI 2006」数字序列
Description 给定一长度为 \(n\) 的数列 \(a\),可将 \(a_i\) 改为任意整数 \(k\),代价为 \(\mid a_i-k\mid\). 问最少改变多少个数能把它变成一个单 ...
- CS5213设计HDMI转VGA带音频方案+设计电路|直接替代AG6200 AG6201
台湾安格AG6200 AG6201专门用于设计HDMI转VGA带音频输出的方案芯片,CS5213是一款HDMI to VGA转换器且结合了HDMI输入接口和模拟RGB DAC输出.带支持片上音频数模转 ...