+54









David Simms
Dan Smith
Frederic Parain
Tobias Hartmann
Roger Riggs
Vicente Romero
Axel Boldt-Christmas
Karen Kinnear
Alex Menkov
Bill Huang
Benoît Maillard
Christian Hagedorn
Chris Plummer
Casper Norrbin
Coleen Phillimore
David Beaumont
Daniel D. Daugherty
Damon Fenacci
David Holmes
Dmitry Samersoff
Eric Caspole
Evgeny Nikitin
Ekaterina Pavlova
Fei Yang
Dan Heidinga
Harold Seigel
Ioi Lam
Ivan Walulya
Jatin Bhateja
Jan Lahoda
Jim Laskey
John R Rose
Joel Sikström
Lois Foltan
Chen Liang
Leonid Mesnik
Matias Saavedra Silva
Marc Chevalier
Mandy Chung
Maurizio Cimadamore
Markus Grönlund
Manuel Hässig
Nick Gasson
Patricio Chilano Mateo
Paul Hübner
Paul Sandoz
Quan Anh Mai
Roberto Castañeda Lozano
Roland Westrelin
Srikanth Adayapalam
Aleksey Shipilev
Stefan Johansson
Sergey Kuksenko
Serguei Spitsyn
Stefan Karlsson
Thomas Stuefe
Thomas Schatzl
Zoltan Majo
Alan Bateman
Jaikiran Pai
Martin Doerr
Richard Reingruber
Feilong Jiang
Daisuke Yamazaki
cc278dbb8a
8389220: Implement JEP 539: Strict Field Initialization in the JVM (Preview) Co-authored-by: David Simms <dsimms@openjdk.org> Co-authored-by: Dan Smith <dlsmith@openjdk.org> Co-authored-by: Frederic Parain <fparain@openjdk.org> Co-authored-by: Tobias Hartmann <thartmann@openjdk.org> Co-authored-by: Roger Riggs <rriggs@openjdk.org> Co-authored-by: Vicente Romero <vromero@openjdk.org> Co-authored-by: Axel Boldt-Christmas <aboldtch@openjdk.org> Co-authored-by: Karen Kinnear <acorn@openjdk.org> Co-authored-by: Alex Menkov <amenkov@openjdk.org> Co-authored-by: Bill Huang <bhuang@openjdk.org> Co-authored-by: Benoît Maillard <bmaillard@openjdk.org> Co-authored-by: Christian Hagedorn <chagedorn@openjdk.org> Co-authored-by: Chris Plummer <cjplummer@openjdk.org> Co-authored-by: Casper Norrbin <cnorrbin@openjdk.org> Co-authored-by: Coleen Phillimore <coleenp@openjdk.org> Co-authored-by: David Beaumont <dbeaumont@openjdk.org> Co-authored-by: Daniel D. Daugherty <dcubed@openjdk.org> Co-authored-by: Damon Fenacci <dfenacci@openjdk.org> Co-authored-by: David Holmes <dholmes@openjdk.org> Co-authored-by: Dmitry Samersoff <dsamersoff@openjdk.org> Co-authored-by: Eric Caspole <ecaspole@openjdk.org> Co-authored-by: Evgeny Nikitin <enikitin@openjdk.org> Co-authored-by: Ekaterina Pavlova <epavlova@openjdk.org> Co-authored-by: Fei Yang <fyang@openjdk.org> Co-authored-by: Dan Heidinga <heidinga@openjdk.org> Co-authored-by: Harold Seigel <hseigel@openjdk.org> Co-authored-by: Ioi Lam <iklam@openjdk.org> Co-authored-by: Ivan Walulya <iwalulya@openjdk.org> Co-authored-by: Jatin Bhateja <jbhateja@openjdk.org> Co-authored-by: Jan Lahoda <jlahoda@openjdk.org> Co-authored-by: Jim Laskey <jlaskey@openjdk.org> Co-authored-by: John R Rose <jrose@openjdk.org> Co-authored-by: Joel Sikström <jsikstro@openjdk.org> Co-authored-by: Lois Foltan <lfoltan@openjdk.org> Co-authored-by: Chen Liang <liach@openjdk.org> Co-authored-by: Leonid Mesnik <lmesnik@openjdk.org> Co-authored-by: Matias Saavedra Silva <matsaave@openjdk.org> Co-authored-by: Marc Chevalier <mchevalier@openjdk.org> Co-authored-by: Mandy Chung <mchung@openjdk.org> Co-authored-by: Maurizio Cimadamore <mcimadamore@openjdk.org> Co-authored-by: Markus Grönlund <mgronlun@openjdk.org> Co-authored-by: Manuel Hässig <mhaessig@openjdk.org> Co-authored-by: Nick Gasson <ngasson@openjdk.org> Co-authored-by: Patricio Chilano Mateo <pchilanomate@openjdk.org> Co-authored-by: Paul Hübner <phubner@openjdk.org> Co-authored-by: Paul Sandoz <psandoz@openjdk.org> Co-authored-by: Quan Anh Mai <qamai@openjdk.org> Co-authored-by: Roberto Castañeda Lozano <rcastanedalo@openjdk.org> Co-authored-by: Roland Westrelin <roland@openjdk.org> Co-authored-by: Srikanth Adayapalam <sadayapalam@openjdk.org> Co-authored-by: Aleksey Shipilev <shade@openjdk.org> Co-authored-by: Stefan Johansson <sjohanss@openjdk.org> Co-authored-by: Sergey Kuksenko <skuksenko@openjdk.org> Co-authored-by: Serguei Spitsyn <sspitsyn@openjdk.org> Co-authored-by: Stefan Karlsson <stefank@openjdk.org> Co-authored-by: Thomas Stuefe <stuefe@openjdk.org> Co-authored-by: Thomas Schatzl <tschatzl@openjdk.org> Co-authored-by: Zoltan Majo <zmajo@openjdk.org> Co-authored-by: Alan Bateman <alanb@openjdk.org> Co-authored-by: Jaikiran Pai <jpai@openjdk.org> Co-authored-by: Martin Doerr <mdoerr@openjdk.org> Co-authored-by: Richard Reingruber <rrich@openjdk.org> Co-authored-by: Feilong Jiang <fjiang@openjdk.org> Co-authored-by: Daisuke Yamazaki <dyama@openjdk.org> Reviewed-by: mcimadamore, liach, darcy, dcubed, aboldtch, coleenp, iklam, jlahoda, dlong, jpai, vklang, heidinga, sspitsyn, cjplummer
189 lines
8.7 KiB
HTML
189 lines
8.7 KiB
HTML
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="generator" content="pandoc" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
|
<title>Migration of JDK Classes to Value Classes</title>
|
|
<style>
|
|
code{white-space: pre-wrap;}
|
|
span.smallcaps{font-variant: small-caps;}
|
|
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
|
div.column{flex: auto; overflow-x: auto;}
|
|
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
|
ul.task-list{list-style: none;}
|
|
ul.task-list li input[type="checkbox"] {
|
|
width: 0.8em;
|
|
margin: 0 0.8em 0.2em -1.6em;
|
|
vertical-align: middle;
|
|
}
|
|
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
|
</style>
|
|
<link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css" />
|
|
<style type="text/css">pre, code, tt { color: #1d6ae5; }</style>
|
|
<!--[if lt IE 9]>
|
|
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
|
|
<![endif]-->
|
|
</head>
|
|
<body>
|
|
<header id="title-block-header">
|
|
<h1 class="title">Migration of JDK Classes to Value Classes</h1>
|
|
</header>
|
|
<nav id="TOC" role="doc-toc">
|
|
<ul>
|
|
<li><a href="#introduction" id="toc-introduction">Introduction</a></li>
|
|
<li><a href="#the-build-process" id="toc-the-build-process">The Build
|
|
Process</a>
|
|
<ul>
|
|
<li><a href="#the-custom-handling-for-the-value-objects-jep"
|
|
id="toc-the-custom-handling-for-the-value-objects-jep">The Custom
|
|
Handling for the Value Objects JEP</a></li>
|
|
<li><a href="#the-general-preview-source-to-binary-pipeline"
|
|
id="toc-the-general-preview-source-to-binary-pipeline">The General
|
|
Preview Source to Binary Pipeline</a></li>
|
|
<li><a href="#non-goals" id="toc-non-goals">Non-Goals</a></li>
|
|
</ul></li>
|
|
<li><a href="#testing" id="toc-testing">Testing</a></li>
|
|
<li><a href="#wrapper-class-caches"
|
|
id="toc-wrapper-class-caches">Wrapper Class Caches</a></li>
|
|
<li><a href="#editing-this-document"
|
|
id="toc-editing-this-document">Editing This Document</a></li>
|
|
</ul>
|
|
</nav>
|
|
<h2 id="introduction">Introduction</h2>
|
|
<p>The Value Objects feature introduces value objects and migrates
|
|
suitable classes to value classes. This means that when preview features
|
|
are enabled, different class files are used for the migrated classes in
|
|
the Java class library.</p>
|
|
<p>To accomplish this, a built JDK uses <em>preview-specific</em> files
|
|
in <code>META-INF/preview</code>, which overrides the regular files of
|
|
the same name. For example,
|
|
<code>META-INF/preview/java/lang/Integer.class</code> overrides
|
|
<code>java/lang/Integer.class</code>.</p>
|
|
<p>The JDK generates preview-specific source files (they may use preview
|
|
language features), compiles class files from them, and distributes
|
|
these class files in <code>META-INF/preview</code>.</p>
|
|
<h2 id="the-build-process">The Build Process</h2>
|
|
<h3 id="the-custom-handling-for-the-value-objects-jep">The Custom
|
|
Handling for the Value Objects JEP</h3>
|
|
<p>The Value Objects JEP requires a few select classes in the
|
|
<code>java.base</code> module to become value classes when preview
|
|
features are enabled.</p>
|
|
<p>The build of <code>java.base</code> module first creates the source
|
|
code of those value classes, done in <a
|
|
href="../make/modules/java.base/gensrc/GensrcValueClasses.gmk"><code>GensrcValueClasses.gmk</code></a>.</p>
|
|
<ol type="1">
|
|
<li><p>A hardcoded list of regular source files are selected for
|
|
preview-specific generation.</p></li>
|
|
<li><p>Extract the content of each regular source file, search for any
|
|
occurrences of <code>/*value*/ class</code> or
|
|
<code>/*value*/ record</code>, and replace with <code>value class</code>
|
|
or <code>value record</code>.</p></li>
|
|
<li><p>The replaced contents are written to the preview-specific
|
|
generated files, located in
|
|
<code>support/gensrc-valueclasses/java.base/</code>. The regular source
|
|
files remain unchanged in their original locations.</p></li>
|
|
<li><p>The general preview source to binary build pipeline recognizes
|
|
the <code>support/gensrc-valueclasses/java.base/</code> directory as
|
|
where the <code>java.base</code> module places its preview-specific
|
|
source files.</p></li>
|
|
</ol>
|
|
<h3 id="the-general-preview-source-to-binary-pipeline">The General
|
|
Preview Source to Binary Pipeline</h3>
|
|
<p>Once the preview-specific source files are ready, they are picked up
|
|
by the build system into a fully automated pipeline handling all modules
|
|
and all outcome images.</p>
|
|
<ol type="1">
|
|
<li><p>The <code>GENERATED_PREVIEW_SUBDIRS</code> variable in <a
|
|
href="../make/common/Modules.gmk"><code>make/common/Modules.gmk</code></a>
|
|
indicates where the source files are found.</p></li>
|
|
<li><p>For each module that has preview-specific source files, a goal is
|
|
created to compile these source files into class files.</p></li>
|
|
<li><p>The class files from each of these tasks reside in
|
|
<code>support/preview/<module></code> for each module.</p></li>
|
|
<li><p>These preview-specific class files and other resources are copied
|
|
to the <code>META-INF/preview</code> directory of the regular output
|
|
directory.</p></li>
|
|
<li><p>At run-time, jimage will pick up the preview-specific overrides
|
|
from <code>META-INF/preview</code> only when preview features are
|
|
enabled.</p></li>
|
|
<li><p>The interim javac used by the build system cannot pick up the
|
|
preview-specific overrides; they must be supplied explicitly with the
|
|
following javac flag for every single module where overrides are
|
|
significant:</p>
|
|
<pre><code>--patch-module <module>=$(SUPPORT_OUTPUTDIR)/preview/<module></code></pre>
|
|
<p>See <a
|
|
href="../make/test/BuildMicrobenchmark.gmk"><code>BuildMicroBenchmarks.gmk</code></a>
|
|
for an example.</p></li>
|
|
</ol>
|
|
<h3 id="non-goals">Non-Goals</h3>
|
|
<p>The Value Objects JEP only plans to introduce value classes that
|
|
are:</p>
|
|
<ol type="1">
|
|
<li><p>In the <code>java.base</code> module.</p>
|
|
<p>There's no plan to migrate other classes in other modules.</p></li>
|
|
<li><p>Migrated from existing classes.</p>
|
|
<p>These classes are available as identity classes when preview features
|
|
are disabled. There's no plan to introduce completely new value
|
|
classes.</p></li>
|
|
</ol>
|
|
<p>Support for other value classes would require significant changes to
|
|
the build system.</p>
|
|
<h2 id="testing">Testing</h2>
|
|
<p>In addition to tests that require preview features to be enabled,
|
|
tests that do not depend on preview features wish to run with preview
|
|
features enabled to ensure compatibility:</p>
|
|
<ol type="1">
|
|
<li><p>Some tests wish to run against the Java SE class library with
|
|
value classes.</p>
|
|
<p>The jtreg tests may be run with
|
|
<code>JTREG=VM_OPTIONS=--enable-preview</code>.</p></li>
|
|
<li><p>Some tests wish to run against their own classes migrated to
|
|
value classes.</p>
|
|
<p>The jtreg <a
|
|
href="testing.html#VALUE_CLASS_PLUGIN">VALUE_CLASS_PLUGIN</a> allows
|
|
tests to migrate their own classes to value classes when running with
|
|
the plugin.</p></li>
|
|
</ol>
|
|
<h2 id="wrapper-class-caches">Wrapper Class Caches</h2>
|
|
<p>Currently, wrapper class caches are retained even when preview
|
|
features are enabled to address performance losses. They have no
|
|
semantic impact to value objects.</p>
|
|
<p>In interpreter or C1 execution in Hotspot, allocations of a value
|
|
object to the heap as a full object with header happen when a value
|
|
object is:</p>
|
|
<ol type="1">
|
|
<li>Loaded from a flat storage (field or array)</li>
|
|
<li>Created by a constructor</li>
|
|
<li>If C2 uses scalarized calling convention, at C2 to C1/interpreter
|
|
calls and returns</li>
|
|
</ol>
|
|
<p>Ideally, C2 can eliminate such allocations, but this does not work if
|
|
the resulting object is stored into references. Unfortunately, many uses
|
|
of boxing conversions store the resulting wrapper objects as
|
|
references.</p>
|
|
<p>For the uses that store wrapper objects to references, if the boxing
|
|
conversion is:</p>
|
|
<ol type="1">
|
|
<li>Returning a value object from a flat cache array</li>
|
|
<li>Calling the value class constructor</li>
|
|
</ol>
|
|
<p>Then we would have heap allocation on every single use.</p>
|
|
<p>To avoid the allocations, we fall back to returning a value object
|
|
from a reference cache array, from which the loaded reference is
|
|
directly storable into a destination that wants a reference without any
|
|
allocation.</p>
|
|
<p>Since Hotspot may create flat arrays if an array of value objects is
|
|
requested by regular Java array creation mechanisms, we use
|
|
<code>ValueClass.newReferenceArray</code> to ensure we always create a
|
|
reference cache array.</p>
|
|
<p>The cache array for value objects may be removed without notice if
|
|
the performance losses from allocations are no longer significant.</p>
|
|
<h2 id="editing-this-document">Editing This Document</h2>
|
|
<p>If you want to contribute changes to this document, edit
|
|
<code>doc/value-class-preview.md</code> and then run
|
|
<code>make update-build-docs</code> to generate the same changes in
|
|
<code>doc/value-class-preview.html</code>.</p>
|
|
</body>
|
|
</html>
|