Java Valhalla Project – Java Valhalla项目

最后修改: 2019年 2月 17日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this article, we’ll look at Project Valhalla – the historical reasons for it, the current state of development and what it brings to the table for the day-to-day Java developer once it’s released.

在本文中,我们将了解项目瓦尔哈拉–它的历史原因、当前的开发状态以及一旦发布,它将为日常的Java开发人员带来什么。

2. Motivation and Reasons for the Valhalla Project

2.瓦尔哈拉项目的动机和原因

In one of his talks, Brian Goetz, Java language architect at Oracle, said one of the main motivations for the Valhalla Project is the desire to adapt the Java language and runtime to modern hardware. When the Java language was conceived (roughly 25 years ago at the time of writing), the cost of a memory fetch and an arithmetic operation was roughly the same.

在他的一次演讲中,Oracle 的 Java 语言架构师 Brian Goetz 说,Valhalla 项目的主要动机之一是希望使 Java 语言和运行时适应现代硬件。当Java语言被构想出来时(在撰写本文时大约是25年前),内存获取和算术操作的成本大致相同。

Nowadays, this has shifted, with memory fetch operations being from 200 to 1,000 times more expensive than arithmetic operations. In terms of language design, this means that indirections leading to pointer fetches have a detrimental effect on overall performance.

如今,这种情况已经发生了转变,内存获取操作的成本是算术操作的200至1,000倍。在语言设计方面,这意味着导致指针获取的间接性对整体性能有不利的影响。

Since most Java data structures in an application are objects, we can consider Java a pointer-heavy language (although we usually don’t see or manipulate them directly). This pointer-based implementation of objects is used to enable object identity, which itself is leveraged for language features such as polymorphism, mutability and locking. Those features come by default for every object, no matter if they are really needed or not.

由于应用程序中的大多数Java数据结构都是对象,我们可以认为Java是一种重指针的语言(尽管我们通常不会直接看到或操作它们)。这种基于指针的对象实现是用来实现对象身份的,而对象身份本身又被用于多态性、可变性和锁定等语言特性。这些特性对于每个对象都是默认的,不管它们是否真的需要。

Following the chain of identity leading to pointers and pointers leading to indirections, with indirections having performance drawbacks, a logical conclusion is to remove those for data structures that have no need for them. This is where value types come into play.

按照身份导致指针和指针导致间接的链条,间接有性能上的缺陷,一个合乎逻辑的结论是为那些不需要它们的数据结构删除它们。这就是价值类型发挥作用的地方。

3. Value Types

3.价值类型

The idea of value types is to represent pure data aggregates. This comes with dropping the features of regular objects. So, we have pure data, without identity. This means, of course, that we’re also losing features we could implement using object identity. Consequentially, equality comparison can only happen based on state. Thus, we can’t use representational polymorphism, and we can’t use immutable or non-nullable objects.

值类型的想法是代表纯粹的数据聚合。这就意味着放弃了常规对象的特征。所以,我们有纯数据,没有身份。当然,这意味着我们也失去了可以用对象身份实现的功能。因此,质量比较只能基于状态进行。因此,我们不能使用表示性多态性,也不能使用不可变或不可归零的对象。

Since we don’t have object identity anymore, we can give up on pointers and change the general memory layout of value types, as compared to an object. Let’s look at a comparison of the memory layout between the class Point and the corresponding value type Point. 

由于我们不再有对象身份,我们可以放弃指针,并改变价值类型的一般内存布局,与对象相比。让我们看看Point类和相应的值类型Point之间的内存布局的比较。

The code and the corresponding memory layout of a regular Point class would be:

一个普通的Point类的代码和相应的内存布局将是。

final class Point {
  final int x;
  final int y;
}

point class memory

On the other hand, the code and corresponding memory layout of a value type Point would be:

另一方面,一个值类型Point的代码和相应的内存布局将是。

value class Point {
  int x;
  int y
}

point value type memory

This allows the JVM to flatten value types into arrays and objects, as well as into other value types. In the following diagram, we present the negative effect of indirections when we use the Point class in an array:

这允许JVM将值类型平移到数组和对象中,以及平移到其他值类型中。在下图中,当我们在数组中使用Point类时,我们展示了间接的负面效果。

java point vaue type array

On the other hand, here we see the corresponding memory structure of a value type Point[]:

另一方面,我们在这里看到了一个值类型Point[]的相应内存结构。

java point vaue type array values

It also enables the JVM to pass value types on the stack instead of having to allocate them on the heap. In the end, this means that we’re getting data aggregates that have runtime behavior similar to Java primitives, such as int or float.

它还使 JVM 能够在堆栈中传递值类型,而不必在堆中分配它们。最终,这意味着我们得到的数据聚合具有类似于Java基元的运行时行为,例如intfloat

But unlike primitives, value types can have methods and fields. We can also implement interfaces and use them as generic types. So we can look at the value types from two different angles:

但与基元不同,值类型可以有方法和字段。我们还可以实现接口,并将其作为通用类型使用。所以我们可以从两个不同的角度来看待值类型。

  • Faster objects
  • User-defined primitives

As additional icing on the cake, we can use value types as generic types without boxing. This directly leads us to the other big Project Valhalla feature: specialized generics.

作为额外的锦上添花,我们可以使用值类型作为泛型,而不需要装箱。这直接将我们引向Project Valhalla的另一个重要特征:专门的泛型。

4. Specialized Generics

4.专门的非专利药

When we want to generify over language primitives, we currently use boxed types, such as Integer for int or Float for float. This boxing creates an additional layer of indirection, thereby defeating the purpose of using primitives for performance enhancement in the first place.

当我们想要在语言基元上生成时,我们目前使用的是盒式类型,例如Integer用于intFloat用于float。这种框定创造了一个额外的指令层,从而违背了首先使用基元来提高性能的目的。

Therefore, we see many dedicated specializations for primitive types in existing frameworks and libraries, like IntStream<T> or ToIntFunction<T>. This is done to keep the performance improvement of using primitives.

因此,我们在现有的框架和库中看到了许多针对原始类型的专门化,比如IntStream<T>ToIntFunction<T>。这样做是为了保持使用基元的性能改进。

So, specialized generics is an effort to remove the needs for those “hacks”. Instead, the Java language strives to enable generic types for basically everything: object references, primitives, value types, and maybe even void.

因此,专门的泛型是为了消除对这些 “黑客 “的需求。相反,Java语言努力使通用类型基本上适用于所有东西:对象引用、基元、值类型,甚至可能是void

5. Conclusion

5.总结

We’ve taken a glimpse at the changes that Project Valhalla will bring to the Java language. Two of the main goals are enhanced performance and less leaky abstractions.

我们已经瞥见了Project Valhalla将给Java语言带来的变化。其中两个主要目标是增强性能和减少泄漏的抽象。

The performance enhancements are tackled by flattening object graphs and removing indirections. This leads to more efficient memory layouts and fewer allocations and garbage collections.

性能的提升是通过扁平化对象图和移除间接因素来解决的。这将导致更有效的内存布局,并减少分配和垃圾回收。

The better abstraction comes with primitives and objects having a more similar behavior when used as Generic types.

更好的抽象性来自于基元和对象在作为通用类型使用时具有更相似的行为。

An early prototype of Project Valhalla, introducing value types into the existing type system, has the code name LW1.

瓦尔哈拉项目的一个早期原型,在现有的类型系统中引入了价值类型,其代码为LW1

We can find more information about Project Valhalla in the corresponding project page and JEPs:

我们可以在相应的项目页面和JEPs中找到更多关于瓦尔哈拉项目的信息。