8389219: Implement JEP 401: Value Objects (Preview) · openjdk/jdk@cc278db

GitHub

4 min read Original article ↗
1+

<!DOCTYPE html>

2+

<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">

3+

<head>

4+

<meta charset="utf-8" />

5+

<meta name="generator" content="pandoc" />

6+

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />

7+

<title>Migration of JDK Classes to Value Classes</title>

8+

<style>

9+

code{white-space: pre-wrap;}

10+

span.smallcaps{font-variant: small-caps;}

11+

div.columns{display: flex; gap: min(4vw, 1.5em);}

12+

div.column{flex: auto; overflow-x: auto;}

13+

div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}

14+

ul.task-list{list-style: none;}

15+

ul.task-list li input[type="checkbox"] {

16+

width: 0.8em;

17+

margin: 0 0.8em 0.2em -1.6em;

18+

vertical-align: middle;

19+

}

20+

.display.math{display: block; text-align: center; margin: 0.5rem auto;}

21+

</style>

22+

<link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css" />

23+

<style type="text/css">pre, code, tt { color: #1d6ae5; }</style>

24+

<!--[if lt IE 9]>

25+

<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>

26+

<![endif]-->

27+

</head>

28+

<body>

29+

<header id="title-block-header">

30+

<h1 class="title">Migration of JDK Classes to Value Classes</h1>

31+

</header>

32+

<nav id="TOC" role="doc-toc">

33+

<ul>

34+

<li><a href="#introduction" id="toc-introduction">Introduction</a></li>

35+

<li><a href="#the-build-process" id="toc-the-build-process">The Build

36+

Process</a>

37+

<ul>

38+

<li><a href="#the-custom-handling-for-the-value-objects-jep"

39+

id="toc-the-custom-handling-for-the-value-objects-jep">The Custom

40+

Handling for the Value Objects JEP</a></li>

41+

<li><a href="#the-general-preview-source-to-binary-pipeline"

42+

id="toc-the-general-preview-source-to-binary-pipeline">The General

43+

Preview Source to Binary Pipeline</a></li>

44+

<li><a href="#non-goals" id="toc-non-goals">Non-Goals</a></li>

45+

</ul></li>

46+

<li><a href="#testing" id="toc-testing">Testing</a></li>

47+

<li><a href="#wrapper-class-caches"

48+

id="toc-wrapper-class-caches">Wrapper Class Caches</a></li>

49+

<li><a href="#editing-this-document"

50+

id="toc-editing-this-document">Editing This Document</a></li>

51+

</ul>

52+

</nav>

53+

<h2 id="introduction">Introduction</h2>

54+

<p>The Value Objects feature introduces value objects and migrates

55+

suitable classes to value classes. This means that when preview features

56+

are enabled, different class files are used for the migrated classes in

57+

the Java class library.</p>

58+

<p>To accomplish this, a built JDK uses <em>preview-specific</em> files

59+

in <code>META-INF/preview</code>, which overrides the regular files of

60+

the same name. For example,

61+

<code>META-INF/preview/java/lang/Integer.class</code> overrides

62+

<code>java/lang/Integer.class</code>.</p>

63+

<p>The JDK generates preview-specific source files (they may use preview

64+

language features), compiles class files from them, and distributes

65+

these class files in <code>META-INF/preview</code>.</p>

66+

<h2 id="the-build-process">The Build Process</h2>

67+

<h3 id="the-custom-handling-for-the-value-objects-jep">The Custom

68+

Handling for the Value Objects JEP</h3>

69+

<p>The Value Objects JEP requires a few select classes in the

70+

<code>java.base</code> module to become value classes when preview

71+

features are enabled.</p>

72+

<p>The build of <code>java.base</code> module first creates the source

73+

code of those value classes, done in <a

74+

href="../make/modules/java.base/gensrc/GensrcValueClasses.gmk"><code>GensrcValueClasses.gmk</code></a>.</p>

75+

<ol type="1">

76+

<li><p>A hardcoded list of regular source files are selected for

77+

preview-specific generation.</p></li>

78+

<li><p>Extract the content of each regular source file, search for any

79+

occurrences of <code>/*value*/ class</code> or

80+

<code>/*value*/ record</code>, and replace with <code>value class</code>

81+

or <code>value record</code>.</p></li>

82+

<li><p>The replaced contents are written to the preview-specific

83+

generated files, located in

84+

<code>support/gensrc-valueclasses/java.base/</code>. The regular source

85+

files remain unchanged in their original locations.</p></li>

86+

<li><p>The general preview source to binary build pipeline recognizes

87+

the <code>support/gensrc-valueclasses/java.base/</code> directory as

88+

where the <code>java.base</code> module places its preview-specific

89+

source files.</p></li>

90+

</ol>

91+

<h3 id="the-general-preview-source-to-binary-pipeline">The General

92+

Preview Source to Binary Pipeline</h3>

93+

<p>Once the preview-specific source files are ready, they are picked up

94+

by the build system into a fully automated pipeline handling all modules

95+

and all outcome images.</p>

96+

<ol type="1">

97+

<li><p>The <code>GENERATED_PREVIEW_SUBDIRS</code> variable in <a

98+

href="../make/common/Modules.gmk"><code>make/common/Modules.gmk</code></a>

99+

indicates where the source files are found.</p></li>

100+

<li><p>For each module that has preview-specific source files, a goal is

101+

created to compile these source files into class files.</p></li>

102+

<li><p>The class files from each of these tasks reside in

103+

<code>support/preview/&lt;module&gt;</code> for each module.</p></li>

104+

<li><p>These preview-specific class files and other resources are copied

105+

to the <code>META-INF/preview</code> directory of the regular output

106+

directory.</p></li>

107+

<li><p>At run-time, jimage will pick up the preview-specific overrides

108+

from <code>META-INF/preview</code> only when preview features are

109+

enabled.</p></li>

110+

<li><p>The interim javac used by the build system cannot pick up the

111+

preview-specific overrides; they must be supplied explicitly with the

112+

following javac flag for every single module where overrides are

113+

significant:</p>

114+

<pre><code>--patch-module &lt;module&gt;=$(SUPPORT_OUTPUTDIR)/preview/&lt;module&gt;</code></pre>

115+

<p>See <a

116+

href="../make/test/BuildMicrobenchmark.gmk"><code>BuildMicroBenchmarks.gmk</code></a>

117+

for an example.</p></li>

118+

</ol>

119+

<h3 id="non-goals">Non-Goals</h3>

120+

<p>The Value Objects JEP only plans to introduce value classes that

121+

are:</p>

122+

<ol type="1">

123+

<li><p>In the <code>java.base</code> module.</p>

124+

<p>There's no plan to migrate other classes in other modules.</p></li>

125+

<li><p>Migrated from existing classes.</p>

126+

<p>These classes are available as identity classes when preview features

127+

are disabled. There's no plan to introduce completely new value

128+

classes.</p></li>

129+

</ol>

130+

<p>Support for other value classes would require significant changes to

131+

the build system.</p>

132+

<h2 id="testing">Testing</h2>

133+

<p>In addition to tests that require preview features to be enabled,

134+

tests that do not depend on preview features wish to run with preview

135+

features enabled to ensure compatibility:</p>

136+

<ol type="1">

137+

<li><p>Some tests wish to run against the Java SE class library with

138+

value classes.</p>

139+

<p>The jtreg tests may be run with

140+

<code>JTREG=VM_OPTIONS=--enable-preview</code>.</p></li>

141+

<li><p>Some tests wish to run against their own classes migrated to

142+

value classes.</p>

143+

<p>The jtreg <a

144+

href="testing.html#VALUE_CLASS_PLUGIN">VALUE_CLASS_PLUGIN</a> allows

145+

tests to migrate their own classes to value classes when running with

146+

the plugin.</p></li>

147+

</ol>

148+

<h2 id="wrapper-class-caches">Wrapper Class Caches</h2>

149+

<p>Currently, wrapper class caches are retained even when preview

150+

features are enabled to address performance losses. They have no

151+

semantic impact to value objects.</p>

152+

<p>In interpreter or C1 execution in Hotspot, allocations of a value

153+

object to the heap as a full object with header happen when a value

154+

object is:</p>

155+

<ol type="1">

156+

<li>Loaded from a flat storage (field or array)</li>

157+

<li>Created by a constructor</li>

158+

<li>If C2 uses scalarized calling convention, at C2 to C1/interpreter

159+

calls and returns</li>

160+

</ol>

161+

<p>Ideally, C2 can eliminate such allocations, but this does not work if

162+

the resulting object is stored into references. Unfortunately, many uses

163+

of boxing conversions store the resulting wrapper objects as

164+

references.</p>

165+

<p>For the uses that store wrapper objects to references, if the boxing

166+

conversion is:</p>

167+

<ol type="1">

168+

<li>Returning a value object from a flat cache array</li>

169+

<li>Calling the value class constructor</li>

170+

</ol>

171+

<p>Then we would have heap allocation on every single use.</p>

172+

<p>To avoid the allocations, we fall back to returning a value object

173+

from a reference cache array, from which the loaded reference is

174+

directly storable into a destination that wants a reference without any

175+

allocation.</p>

176+

<p>Since Hotspot may create flat arrays if an array of value objects is

177+

requested by regular Java array creation mechanisms, we use

178+

<code>ValueClass.newReferenceArray</code> to ensure we always create a

179+

reference cache array.</p>

180+

<p>The cache array for value objects may be removed without notice if

181+

the performance losses from allocations are no longer significant.</p>

182+

<h2 id="editing-this-document">Editing This Document</h2>

183+

<p>If you want to contribute changes to this document, edit

184+

<code>doc/value-class-preview.md</code> and then run

185+

<code>make update-build-docs</code> to generate the same changes in

186+

<code>doc/value-class-preview.html</code>.</p>

187+

</body>

188+

</html>