一时冲动:“通往瓦尔哈拉之路的冒险”

通过所有有关Java 9和Project Jigsaw的讨论,我们不应忽视Java的另一重大变化。 希望在第10版或第11版中, Valhalla项目能够实现并介绍价值类型和专业化。

那么这是怎么回事,项目进展如何,面临什么挑战? 几天前,Oracle Java语言架构师和Valhalla项目负责人Brian Goetz在JVM Language Summit 2015上的一次演讲中回答了这些问题。

我们来看一下。

总览

这篇文章将介绍Goetz演讲“冒险到Valhalla的道路”的四个部分中的三个。

他以序言开头,我为那些尚不了解Valhalla项目的人提供了一些补充说明。 Goetz继续展示这两个原型,其中第一个原型于去年公开发布,第二个原型仅在两周前发布。 由于这篇文章已经足够长了,因此我将不讨论他关于未来实验的最后一部分。 如果您觉得这个话题很有趣,那么一定要看整个演讲!

全文中的所有引用均来自幻灯片或逐字记录。

谈话

这里是谈话:

(顺便说一句,JVMLS团队在几个小时内将所有讨论都在线上获得了赞誉!)

如果您可以节省50分钟,那就去看吧! 然后,无需阅读这篇文章。

要点

序幕

Valhalla项目涉及的两个主要主题是价值类型和通用专业化 。

值类型

前者将允许用户定义具有相同属性(如不变性,相等性而不是标识)的“类似int”的类型,以及由此产生的性能优势。 它们之前是Java 8的基于值的类 。

(除非另有说明,否则当本文章的其余部分讨论基元时,将包括值类型。)

通用专业化

随着每个人都声明自己的原始类型,泛型无法在它们之上工作的事实(即,没有ArrayList<int> )引起的问题变得令人无法忍受。 从概念的角度来看,虽然必须对原语进行装箱,但它具有显着的性能成本。

首先,存储对象而不是基元会花费额外的内存(例如,对象标头)。 然后,更糟的是,装箱会破坏缓存的局部性 。 当CPU缓存Integer -array时,它仅获取指向实际值的指针。 提取这些是额外的随机内存访问。 当CPU主要在等待高速缓存未命中时,这种额外级别的间接开销将付出巨大的代价,并可能破坏并行化。

因此,Valhalla项目的另一个目标是扩大参数多态性的范围,以使泛型能够覆盖基元。 为了获得成功,JVM应该使用基元而不是用于通用类中的通用字段,参数和返回值的框。

由于可能的实现方式,这称为通用专门化

因此,泛型需要与值类型很好地配合使用,并且原语可以伴随而来。

泛型的现状

由于擦除,类型变量被擦除到其边界,即ArrayList<Integer>实际上变为ArrayList<Object> (或者只是ArrayList )。 这样的界限必须是所有可能实例化的超类型。 但是Java在基本类型和引用类型之上没有类型。

另外,JVM字节码指令通常是正交的,即沿相同的行分割。 一个aloadastore只能移动引用。 专业变体具有用于原语,如iloadistoreint 。 没有字节码可以同时移动引用和int

因此,类型系统和字节码指令集都无法完成生成原语的任务。 十多年前开发出仿制药时,这已广为人知,作为一种折衷,决定是根本不允许这样做。

今天的问题来自昨天的解决方案……

兼容性!

当然,Valhalla项目下发生的所有事情都必须向后兼容。 这有几种形式:

  • 二进制兼容性:现有的字节码,即已编译的类文件,必须继续表示同一意思。 这样可以确保依赖项继续工作而无需重新编译。
  • 源代码兼容性:源文件必须继续具有完全相同的含义,因此重新编译它们一定不能“仅仅因为语言已更改”而更改任何内容。
  • 迁移兼容性:来自不同Java版本的编译类必须协同工作,以允许一次迁移一个依赖项。

另一个要求是,不要使JVM模仿太多的Java语言。 这样做将迫使其他JVM语言处理Java语言的语义。

原型模型1:使其工作

大约一年前,Goetz和他的同事提出了第一个专业化实验性实施方案。

想法

在此原型中,编​​译器继续生成已擦除的类文件,但使用其他类型信息对其进行了扩充。

VM会忽略此信息,但将由专化器使用 ,这是类加载器的新组成部分。 后者将识别何时需要带有原始类型参数的类,并让专门化工具从已删除但已增强的类文件中即时生成它。

通过擦除,一个类的所有通用实例都使用相同的类文件。 相反,为每种原始类型创建一个新的类文件称为specialization

细节

在该原型中,使用“名称处理技术”描述了专门的类。 类名后面附加一个字符串,该字符串指示哪种类型参数专用于哪个原语。 例如, ArrayList${0=I}意思是“用第一个类型变量int实例化的ArrayList ”。

在专业化期间,必须更改签名字节码。 为了正确地做到这一点,专门化者需要知道哪些Object出现(所有通用类型都被擦除了)必须被专门化为哪种类型。 所需的签名信息已经大部分存在于类文件中,并且原型使用附加的类型元数据注释字节码。

从Goetz的8:44开始 ,它给出了几个如何进行的示例。 他还使用它们来指出这种实现必须要注意的一些细节,例如泛型方法的主题。

我知道那是很多快速的挥手。 关键是,这很简单,但是却有很多复杂性。

摘要

该实验表明,基于类文件元数据的即时专业化无需更改虚拟机即可工作。 这些都是重要的成就,但也有不利的弊端。

首先,它需要实现一组复杂的细节。

其次,也许是最重要的是,它具有有问题的类型系统特征。 在不更改VM的情况下,仍然没有intString公共超类型,因此也没有ArrayList<int>ArrayList<String>公共超类型。 这意味着没有办法声明“ ArrayList任何实例”。

第三,这具有可怕的代码共享属性。 即使ArrayList<int>ArrayList<String>大部分代码是相同的,也可以在ArrayList${0=I}ArrayList复制它们。

死亡减少1000点。

原型模型2:抢救通配符

第二个非常新的原型解决了有问题的类型系统特征。

问题

当前,无界通配符表示“类的任何实例”,例如ArrayList<?>表示“任何ArrayList ”。 它们被大量使用,尤其是库开发人员。 在ArrayList<int>ArrayList<String>是不同类的系统中,通配符可能更为重要,因为它们弥合了它们之间的鸿沟并“表达了基本的ArrayList -ness”。

但是,如果我们假设ArrayList<?>ArrayList<int>的超类型,那么我们最终会遇到需要多个类继承的情况。 原因是ArrayList<T>扩展了AbstractList<T>因此我们也希望ArrayList<int>扩展AbstractList<int> 。 现在, ArrayList<int>将扩展ArrayList<?>AbstractList<int> (它们没有继承关系)。

在通往瓦尔哈拉项目的多重继承路上

(请注意,与当前泛型的区别在于擦除。在VM中, ArrayList<Integer>ArrayList<?>是同一类ArrayList,可以自由扩展AbstractList。)

根本原因是,虽然ArrayList<?>看起来像是“ any ArrayList ”,但实际上是ArrayList< ?。 扩展Object> ,即“引用类型上的任何ArrayList ”。

想法

原型引入了带有refvalany的新的通配符层次结构:

  • ref包含所有引用类型并替换?
  • val包含所有原语和值类型(原型当前不支持该值,并且在谈话中未提及,但已在Valhalla邮件列表中宣布 )
  • any包含refval

专用类的多重继承将通过使用合成接口表示任意类型来解决。 ArrayList<int>将因此扩展AbstractList<int>并实现ArrayList<any>

细节

层次结构

ArrayList<ref> (即ArrayList<?> )将继续为已擦除类型。

为了表示ArrayList<any> ,编译器将创建一个接口ArrayList$any 。 它会由ArrayList生成的所有类(例如ArrayList<int>和已擦除的ArrayList )实现,并将扩展与超类相对应的所有综合接口,例如AbstractList$anyAbstractList<any>

在通往Valhalla任何接口的道路上冒险

该接口将包含该类的所有方法的声明以及其字段的访问器。 因为仍然没有对象和基元的公共超类型,所以必须将其通用参数和返回类型装箱。

但是,如果类以ArrayList<any>的方式访问而该访问是直接针对的,例如ArrayList<int> ,则只需采取这种绕行方式。 因此,装箱的性能成本仅由使用通配符的开发人员承担,而使用原始专业化的代码直接获得预期的改进性能。

它干净利落地工作。

你不应该相信我,事情变得复杂了。 但这是个好故事。 我们会继续前进。

从Goetz的26:33开始,提供一些示例来解释一些细节。

辅助功能

可访问性是VM需要更改的区域。 到目前为止,接口不能具有私有或包可见的方法。 (在Java 9中,可以使用私有默认方法,但这在这里无济于事,因为需要实现。)

一个联系在一起但更老的问题是,即使VM不允许这样做,外部类及其内部类也可以互相访问私有成员,因为VM不允许这样做,因为它们都是无关的类。 当前,这是通过生成桥接方法(即具有较高可见性的方法,而不是无法访问的私有成员)来解决的。

为专门的类创建更多的桥接方法将是可能的,但是很费力。 相反,可能的更改是创建类嵌套的概念。 它包含所有专用类和内部类,并且VM允许访问嵌套内部的私有成员。

这将使语言的解释与VM的解释保持一致,VM的语言将所有专业化知识和内部类作为一个单元,而VM直到现在只看到一堆不相关的类。

数组

通用方法也可以采用或返回数组。 但是,尽管专业化可以将一个int到一个Object上,但是int[]Object[]并且将每个单独的int装箱是一个糟糕的想法。

Arrays 2.0可能在这里有所帮助。 因为讨论需要基本熟悉该提案,所以我不会详细介绍。 总而言之,看起来他们将解决问题。

摘要

语言的更改在概念上很简单。 在没有任何变化的情况下。 类型变量可以用任何修饰,如果需要将实例分配给通配符类型,则通配符也必须使用任何通配符。

通过使用原始类型和引用类型(例如ArrayList<any> )的泛型类的通用超类型,所得的编程模型更加合理。 在谈到他的团队将Stream API移植到此原型的经验时,Goetz说:

真的很顺利。 这正是您想要的。 大约70%的代码刚刚消失,因为所有手工专门化的原始东西都消失了,然后许多支持手工专门化的复杂机制也消失了,三年级的学生可以成为一个简单的图书馆写。 因此,我们认为这是一个非常成功的实验。

与现有代码的兼容性也很好。

不幸的是,第一个原型的不良代码共享属性仍然存在。 ArrayList<int>ArrayList<String>仍然是不同的类,它们非常相似,但不共享任何代码。 在下一篇文章中我将不介绍的下一部分将解决该问题,并提出解决该问题的可能方法。

反射

谈话非常密集,涉及很多领域。 我们已经看到,值类型的引入和期望的性能改进需要通用的专业知识,因此可以减少甚至防止装箱。

第一个原型通过在装入类时专门化类来实现这一目标,而无需更改JVM。 但是,存在一个问题,即一个类的所有实例都没有通用的超类型,因为原始类型和引用类型参数会产生完全不相关的类。 第二个原型引入了通配符refvalany并使用合成接口表示任意类型。

这一切都非常令人兴奋,我等不及要尝试一下! 不幸的是,我要去度假,所以我不能一会儿了。 愚蠢的现实生活…别在我走后就破坏事物!

翻译自: https://www.javacodegeeks.com/2015/08/impulse-adventures-on-the-road-to-valhalla.html

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

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

相关文章

小程序分包

一、小程序分包 微信文档写的够清楚了 使用分包 | 微信开放文档 &#xff08;1&#xff09;常规分包注意点&#xff1a; 每个分包只能引用主包和自己的资源 &#xff08;2) 独立分包注意点&#xff1a;特别麻烦 懒得用了吧 独立分包中不能依赖主包和其他分包中的内容 …

解决Sublime Text3莫名的中文乱码问题

有好几回用Sublime Text3写着中英混杂的文字的时候&#xff0c;会突然就弹出警告说什么编码不行&#xff0c;然后点击确定后&#xff0c;原来的中文全都乱码了&#xff1a; 然后即使按ctrlz撤回也没用&#xff0c;重新打开也没用&#xff0c;用记事本的转换ansi、unicode等方式…

try catch finally的用法

1、不使用try...catch出现异常后&#xff0c;后面的代码都不会运行了 login() {console.log(b);console.log(hhhhhhhh);}, 2、使用了try...catch出现异常后&#xff0c;try...catch后的代码还会继续运行 login() {try{console.log(b);}catch (e){console.log(e);}console.log…

网站优化第一次网页加载的速度的办法与思路。

网站重新开发了一次&#xff0c;第一次部署到测试网络&#xff0c;访问速度很慢&#xff0c;差不多第一次加载得需要40秒&#xff0c;太慢了&#xff0c;这里简单总结一下。 当然&#xff0c;还有一些无用的.MAP文件都可以删除&#xff0c;图片可以在线压缩一下&#xff0c;代码…

我的Serverless实战——大前端趋势之Serverless从入门到天黑

导读&#xff1a;大厂都在做Serverless&#xff0c;他到底是什么东东呢&#xff1f;可能很多人都没有听说过&#xff0c;听说这个是大前端的一个趋势&#xff0c;最近两年比较火&#xff0c;如果你还没有听说过&#xff0c;那你就需要注意啦。今天孙叫兽带大家了解一下Serverle…

element ui upload上传文件成功后,清除默认的列表。

问题描述&#xff1a;每次提交之后&#xff0c;这个上传按钮会有默认的列表&#xff0c;其实刷新这个默认列表就没了。 清除标记位置的办法&#xff1a; 清除列表&#xff1a;&#xff08;上传成功后&#xff0c;清空列表&#xff09; 效果图&#xff1a;

处理网络请求qs、图片转base64的优劣

一、引入qs这个库&#xff0c;更好的处理网络请求传参。 qs.parse let url http://item.taobao.com/item.htm?a1&b2&c&dxxx&e; let data qs.parse(url.split(?)[1]);// data的结果是 {a: 1, b: 2, c: , d: xxx, e: }qs.stringify 二、图片文件转为base6…

花了一天的时间给粉丝做了一个小米官网(高仿)

身为前端程序员&#xff0c;经常会找几个官网试试手&#xff0c;哈哈&#xff0c;这次拿小米官网试试手吧。 目录 效果图&#xff1a; 项目结构 index.html index.css js 下载地址&#xff1a;点我下载 效果图&#xff1a; 项目结构 index.html <!DOCTYPE html> &l…

uniapp踩坑指南之坑多到写不完

1、sticky:到达指定位置时&#xff0c;就停留在那里不动了。当发现可以走时&#xff0c;立马就走了。 如果走不了就不会动了&#xff0c;就会一直在那里。 https://www.cnblogs.com/byeyear/p/11999334.html 设置了sticky定位的元素相对于第一个定位不为static的父级元素的位置…

小程序引入百度地图与uni.getLocation的使用

一、小程序引入百度地图 1、当你不需要引入整个地图展示&#xff0c;只需要引入某些功能的时候&#xff0c;可以直接调用服务端api。 2、访问百度地图的任何api都需要密钥。 流程&#xff1a; 3、在小程序端配置请求合法域名&#xff1a;https://api.map.baidu.com 4、直接使…

当年上大学时,编程老师让我们用html+CSS实现一个天猫官网

纯用htmlcss实现一个天猫首页还是挺考验基本功的&#xff0c;完全考验自己的CSS功底。 目录 效果图 项目结构 index.html 源码下载&#xff1a;点我下载 效果图 项目结构 主要由htmlcss组成。 index.html <!doctype html> <html lang"en"><head&g…

微服务实战系列之Dubbo(上)

前言 随着一年一度冬至的到来&#xff0c;2023的步伐也将远去。而博主的系列文章&#xff0c;也将从今天起&#xff0c;越来越聚焦如何构建微服务“内核”上。前序系列文章几乎囊括了微服务的方方面面&#xff0c;无论使用什么框架、组件或工具&#xff0c;皆可拿来用之。 那么…

多线程图解

关于多线程一直是我们学习iOS的一个重点&#xff0c;不仅是面试中经常被问到的问题&#xff0c;而且我们开发过程过程中经常会用到的技术&#xff0c;下面是一张关于多线程的图解&#xff0c;希望可以帮助大家学习多线程的开发。 转载于:https://www.cnblogs.com/lyy-5518/p/53…

spring作业_Spring和石英:多作业计划服务

spring作业作业调度对于应用程序来说是如此重要。 尤其是在大型项目中&#xff0c;处理大量工作可能是一个问题。 Spring和Quartz为解决该问题带来了巨大的好处。 本文展示了如何通过使用Spring和Quartz轻松地计划多个作业。 二手技术&#xff1a; JDK 1.6.0_21 春天3.1.1 石…

react常用知识点总结

1、什么是jsx JSX是JavaScript的扩展语法,这种<></>标签的写法就是 JSX。JSX 编写的组件通过预处理器 babel 解析后,再交给 React 库渲染到指定父容器下,形成最终html页面,供浏览器解析和显示。 JSX会被babel编译为&#xff1a;React.createElement()&#xff0c…

前端导入导出文件

一、导出 1、返回值是url&#xff1a;创建个a标签即可 printRecord(params).then((response) > {if (response.success) {let a document.createElement(a);//创建a标签//从新页面打开&#xff0c;下载的话不需要这个&#xff0c;打开一个图片需要从新页面打开a.setAttrib…

vue进阶

1、vue-cli 使用 在开发中&#xff0c;需要打包的东西不止是js、css、html。还有更多的东西要处理&#xff0c;这些插件和加载器如果我们一一去添加就会比较麻烦&#xff0c;vue官方提供了一个快速搭建vue项目的脚手架&#xff0c;使用它能快速的构建一个web工程模板。 官网&…

Diff 算法核心原理

什么是虚拟DOM 讲Diff算法前&#xff0c;我先给大家讲一讲什么是虚拟DOM吧。这有利于后面大家对Diff算法的理解加深。 虚拟DOM是一个对象&#xff0c;一个什么样的对象呢&#xff1f;一个用来表示真实DOM的对象&#xff0c;要记住这句话。我举个例子&#xff0c;请看以下真实…

python 列表 字典 读写文件:pickle模块的基本使用

建议大家使用cPickle&#xff0c;速度更快&#xff01;&#xff01;&#xff01; python数据持久存储&#xff1a;pickle模块的基本使用&#xff08;转载&#xff09; 作者: pzxbc出处: http://pzxbc.cnblogs.com/本文版权归作者和博客园共有&#xff0c;欢迎转载&#xff0c;但…

first-child、first-of-type等属性的差别

1、xxx:first-child 伪类 xxx作为第一个子元素 //p元素作为第一个子元素的都会变色 p:first-child { background:yellow; } //p作为父元素的 第一个子元素。不要求第一个元素的类型 p>:first-child {background:yellow; }//p作为父元素的 第一个子元素。要求第一个元素的类…