CINXE.COM
The OpenJDK Developers' Guide – OpenJDK Developers’ Guide
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii" /><meta http-equiv="Content-Type" content="text/html; charset=us-ascii" /><meta http-equiv="Content-Style-Type" content="text/css" /><meta name="generator" content="pandoc" /><title>The OpenJDK Developers' Guide – OpenJDK Developers’ Guide</title><link rel="shortcut icon" href="../images/nanoduke.ico" /><link rel="stylesheet" type="text/css" href="../page.css" /><script type="text/javascript" src="../page.js"><noscript></noscript></script><script src="https://cdn.usefathom.com/script.js" data-site="KCYJJPZX" defer="yes"></script><style type="text/css"> /**/ code{white-space: pre-wrap;} span.smallcaps{font-variant: small-caps;} span.underline{text-decoration: underline;} div.column{display: inline-block; vertical-align: top; width: 50%;} div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} ul.task-list{list-style: none;} pre > code.sourceCode { white-space: pre; position: relative; } pre > code.sourceCode > span { display: inline-block; line-height: 1.25; } pre > code.sourceCode > span:empty { height: 1.2em; } .sourceCode { overflow: visible; } code.sourceCode > span { color: inherit; text-decoration: inherit; } div.sourceCode { margin: 1em 0; } pre.sourceCode { margin: 0; } @media screen { div.sourceCode { overflow: auto; } } @media print { pre > code.sourceCode { white-space: pre-wrap; } pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; } } pre.numberSource code { counter-reset: source-line 0; } pre.numberSource code > span { position: relative; left: -4em; counter-increment: source-line; } pre.numberSource code > span > a:first-child::before { content: counter(source-line); position: relative; left: -1em; text-align: right; vertical-align: baseline; border: none; display: inline-block; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; padding: 0 4px; width: 4em; color: #aaaaaa; } pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; } div.sourceCode { } @media screen { pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; } } code span.al { color: #ff0000; font-weight: bold; } /* Alert */ code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */ code span.at { color: #7d9029; } /* Attribute */ code span.bn { color: #40a070; } /* BaseN */ code span.bu { } /* BuiltIn */ code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */ code span.ch { color: #4070a0; } /* Char */ code span.cn { color: #880000; } /* Constant */ code span.co { color: #60a0b0; font-style: italic; } /* Comment */ code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */ code span.do { color: #ba2121; font-style: italic; } /* Documentation */ code span.dt { color: #902000; } /* DataType */ code span.dv { color: #40a070; } /* DecVal */ code span.er { color: #ff0000; font-weight: bold; } /* Error */ code span.ex { } /* Extension */ code span.fl { color: #40a070; } /* Float */ code span.fu { color: #06287e; } /* Function */ code span.im { } /* Import */ code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */ code span.kw { color: #007020; font-weight: bold; } /* Keyword */ code span.op { color: #666666; } /* Operator */ code span.ot { color: #007020; } /* Other */ code span.pp { color: #bc7a00; } /* Preprocessor */ code span.sc { color: #4070a0; } /* SpecialChar */ code span.ss { color: #bb6688; } /* SpecialString */ code span.st { color: #4070a0; } /* String */ code span.va { color: #19177c; } /* Variable */ code span.vs { color: #4070a0; } /* VerbatimString */ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */ .display.math{display: block; text-align: center; margin: 0.5rem auto;} /**/ </style><link rel="stylesheet" href="guidestyle.css" type="text/css" /></head><body><div id="main"> <div id="header"> <h1 class="title">OpenJDK Developers’ Guide</h1> </div> <div id="TOC"> <ul> <li><a href="#introduction">Introduction</a> <ul> <li><a href="#openjdk">OpenJDK</a></li> <li><a href="#author-committer-reviewer">Author, Committer, Reviewer</a> <ul> <li><a href="#becoming-an-author">Becoming an Author</a></li> <li><a href="#becoming-a-committer">Becoming a Committer</a></li> <li><a href="#becoming-a-reviewer">Becoming a Reviewer</a></li> <li><a href="#non-trivialsignificant-changes">Non-trivial/Significant changes</a></li> </ul> </li> </ul> </li> <li><a href="#contributing-to-an-openjdk-project">Contributing to an OpenJDK Project</a> <ul> <li><a href="#things-to-consider-before-proposing-changes-to-openjdk-code">Things to consider before proposing changes to OpenJDK code</a></li> <li><a href="#i-have-a-patch-what-do-i-do">I have a patch, what do I do?</a> <ul> <li><a href="#sign-the-oca">1. Sign the OCA</a></li> <li><a href="#socialize-your-change">2. Socialize your change</a></li> <li><a href="#find-a-sponsor">3. Find a Sponsor</a></li> <li><a href="#create-a-tracking-issue-in-jbs">4. Create a tracking issue in JBS</a></li> <li><a href="#get-acquainted-with-local-process">5. Get acquainted with local process</a></li> </ul> </li> <li><a href="#why-is-my-change-rejected">Why is my change rejected?</a></li> </ul> </li> <li><a href="#mailing-lists">Mailing Lists</a> <ul> <li><a href="#changing-your-email-address">Changing your email address</a></li> </ul> </li> <li><a href="#code-conventions">Code Conventions</a></li> <li><a href="#jbs---jdk-bug-system">JBS - JDK Bug System</a> <ul> <li><a href="#filing-an-issue">Filing an issue</a> <ul> <li><a href="#types-of-issues">Types of issues</a></li> <li><a href="#indicating-what-releases-an-issue-is-applicable-to">Indicating what releases an issue is applicable to</a></li> <li><a href="#things-to-keep-in-mind-when-requesting-an-improvement">Things to keep in mind when requesting an improvement</a></li> <li><a href="#implementing-a-large-change">Implementing a large change</a></li> <li><a href="#implementing-a-jep">Implementing a JEP</a></li> </ul> </li> <li><a href="#issue-states">Issue states</a></li> <li><a href="#triaging-an-issue">Triaging an issue</a> <ul> <li><a href="#sensitive-information-e.g.-hs_err.log">Sensitive information (e.g. hs_err.log)</a></li> </ul> </li> <li><a href="#updating-an-issue-while-fixing">Updating an issue while fixing</a> <ul> <li><a href="#linking-issues">Linking Issues</a></li> </ul> </li> <li><a href="#resolving-or-closing-an-issue">Resolving or Closing an issue</a> <ul> <li><a href="#closing-issues-as-duplicates">Closing issues as duplicates</a></li> <li><a href="#closing-issues-without-knowing-what-fixed-it">Closing issues without knowing what fixed it</a></li> <li><a href="#closing-incomplete-issues">Closing incomplete issues</a></li> </ul> </li> <li><a href="#verifying-an-issue">Verifying an issue</a></li> <li><a href="#removing-an-issue">Removing an issue</a></li> <li><a href="#jbs-labels">JBS labels</a></li> <li><a href="#jbs-label-dictionary">JBS label dictionary</a></li> </ul> </li> <li><a href="#cloning-the-jdk">Cloning the JDK</a> <ul> <li><a href="#working-with-git-branches">Working with git branches</a></li> <li><a href="#generating-an-ssh-key">Generating an SSH key</a></li> </ul> </li> <li><a href="#making-a-change">Making a Change</a> <ul> <li><a href="#working-with-the-csr">Working with the CSR</a></li> <li><a href="#copyright-headers">Copyright Headers</a></li> </ul> </li> <li><a href="#building-the-jdk">Building the JDK</a> <ul> <li><a href="#configuration-options">Configuration options</a> <ul> <li><a href="#working-with-multiple-configurations">Working with multiple configurations</a></li> </ul> </li> <li><a href="#make-targets">Make targets</a></li> </ul> </li> <li><a href="#testing-the-jdk">Testing the JDK</a> <ul> <li><a href="#jtreg">jtreg</a> <ul> <li><a href="#running-openjdk-jtreg-tests">Running OpenJDK jtreg tests</a></li> </ul> </li> <li><a href="#gtest">GTest</a> <ul> <li><a href="#running-openjdk-gtests">Running OpenJDK GTests</a></li> </ul> </li> <li><a href="#github-actions">GitHub actions</a></li> <li><a href="#excluding-a-test">Excluding a test</a> <ul> <li><a href="#problemlisting-jtreg-tests">ProblemListing jtreg tests</a></li> <li><a href="#exclude-jtreg-tests-using-ignore">Exclude jtreg tests using <code>@ignore</code></a></li> <li><a href="#dealing-with-jbs-bugs-for-test-exclusion">Dealing with JBS bugs for test exclusion</a></li> </ul> </li> <li><a href="#backing-out-a-change">Backing out a change</a> <ul> <li><a href="#how-to-work-with-jbs-when-a-change-is-backed-out">How to work with JBS when a change is backed out</a></li> <li><a href="#how-to-work-with-git-when-a-change-is-backed-out">How to work with git when a change is backed out</a></li> </ul> </li> <li><a href="#backing-out-a-backport">Backing out a backport</a> <ul> <li><a href="#rationale-for-using-this-model">Rationale for using this model</a></li> </ul> </li> </ul> </li> <li><a href="#working-with-pull-requests">Working With Pull Requests</a> <ul> <li><a href="#think-once-more">Think once more</a></li> <li><a href="#rebase-before-creating-the-pr">Rebase before creating the PR</a></li> <li><a href="#final-check-before-creating-the-pr">Final check before creating the PR</a></li> <li><a href="#life-of-a-pr">Life of a PR</a></li> <li><a href="#webrevs">Webrevs</a></li> <li><a href="#file-storage-for-openjdk-artifacts---cr.openjdk.org">File storage for OpenJDK artifacts - <code>cr.openjdk.org</code></a> <ul> <li><a href="#get-your-ssh-key-installed">Get your SSH key installed</a></li> </ul> </li> </ul> </li> <li><a href="#reviewing-and-sponsoring-a-change">Reviewing and Sponsoring a Change</a> <ul> <li><a href="#responsibilities-of-a-reviewer">Responsibilities of a Reviewer</a></li> <li><a href="#reviewing-a-change-on-github">Reviewing a change on GitHub</a> <ul> <li><a href="#conversation">Conversation</a></li> <li><a href="#files-changed">Files changed</a></li> <li><a href="#trivial-changes">Trivial changes</a></li> </ul> </li> <li><a href="#volunteering-to-sponsor-a-contribution">Volunteering to sponsor a contribution</a></li> <li><a href="#responsibilities-of-a-sponsor">Responsibilities of a sponsor</a></li> </ul> </li> <li><a href="#backporting">Backporting</a> <ul> <li><a href="#backporting-to-a-feature-release-stabilization-branch">Backporting to a feature release stabilization branch</a></li> <li><a href="#backporting-multiple-related-changes">Backporting multiple related changes</a></li> <li><a href="#working-with-backports-in-jbs">Working with backports in JBS</a></li> <li><a href="#requesting-approvals-for-backports">Requesting approvals for backports</a></li> <li><a href="#using-the-skara-tooling-to-help-with-backports">Using the Skara tooling to help with backports</a></li> <li><a href="#how-to-fix-an-incorrect-backport-creation-in-jbs">How to fix an incorrect backport creation in JBS</a></li> </ul> </li> <li><a href="#release-notes">Release Notes</a> <ul> <li><a href="#writing-a-release-note">Writing a release note</a></li> <li><a href="#general-conventions-for-release-notes">General conventions for release notes</a></li> <li><a href="#advanced-options">Advanced options</a></li> <li><a href="#rn-labels">RN-labels</a></li> <li><a href="#querying-the-release-notes">Querying the release notes</a></li> </ul> </li> <li><a href="#the-jdk-release-process">The JDK Release Process</a> <ul> <li><a href="#release-cycle">Release cycle</a></li> <li><a href="#milestones-and-phases">Milestones and phases</a> <ul> <li><a href="#push-or-defer-during-ramp-down">Push or defer during ramp down</a></li> <li><a href="#deferring-p1-and-p2-bugs">Deferring P1 and P2 bugs</a></li> </ul> </li> </ul> </li> <li><a href="#project-maintenance">Project Maintenance</a> <ul> <li><a href="#merging-jdk-mainline-into-a-project-repository">Merging JDK mainline into a Project repository</a> <ul> <li><a href="#init---done-once">Init - done once</a></li> <li><a href="#performing-the-merge">Performing the merge</a></li> <li><a href="#test-before-integration">Test before integration</a></li> <li><a href="#the-commit-push-and-pr">The commit, push, and PR</a></li> <li><a href="#sharing-the-work">Sharing the work</a></li> </ul> </li> </ul> </li> <li><a href="#hotspot-development">HotSpot Development</a> <ul> <li><a href="#logging">Logging</a> <ul> <li><a href="#enabling-logging">Enabling logging</a></li> </ul> </li> </ul> </li> <li><a href="#code-owners">Code Owners</a> <ul> <li><a href="#area-mailing-lists">Area mailing lists</a></li> <li><a href="#directory-to-area-mapping">Directory to area mapping</a> <ul> <li><a href="#directories-removed">Directories removed</a></li> </ul> </li> </ul> </li> <li><a href="#about-this-guide">About This Guide</a></li> </ul> </div> <h1 id="introduction">Introduction</h1> <p>Welcome to the OpenJDK Developers’ Guide!</p> <p>The OpenJDK Community is the place to collaborate on open-source implementations of the Java Platform, Standard Edition, and related <a href="https://openjdk.org/bylaws#project">Projects</a>. It was created in November 2006, when initial portions of the JDK source code were published under the GPLv2 license.</p> <p>In order to work together efficiently, clear directions are sometimes needed to avoid misconceptions and to align developers’ views of terminology and process. The OpenJDK Community is a fairly pragmatic place. “Do the right thing” is most often the right course of action. Still, if people do things in the same right way then everyone’s work becomes more transparent and easier for others to follow. For this reason most parts of the development process have standard flows that are the recommended ways to do things.</p> <p>The goal of this guide is to answer questions that developers of the JDK might have around development process, tooling, standards, and so forth. The formal rules and processes are described in other documents, such as <a href="https://openjdk.org/jeps/1">JEP 1</a> for the JDK Enhancement-Proposal & Roadmap Process, and <a href="https://openjdk.org/jeps/3">JEP 3</a> for the JDK Release Process. This guide is meant to be a complement to such documents, with tutorials and examples for how to follow these rules and how to work together with the rest of the OpenJDK Community.</p> <p>There are many common use cases that aren’t detailed in the formal process. This guide suggests how to work in such cases.</p> <h2 id="openjdk">OpenJDK</h2> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://openjdk.org/bylaws#group">OpenJDK Groups</a></li> <li><a href="https://openjdk.org/bylaws#project">OpenJDK Projects</a></li> <li><a href="https://openjdk.org/bylaws#general-roles">OpenJDK General Roles (Participant, Contributor, Member)</a></li> <li><a href="https://openjdk.org/bylaws#project-roles">OpenJDK Project Roles (Author, Committer, Reviewer)</a></li> </ul> </div> <p>OpenJDK consists of a number of <a href="https://openjdk.org/bylaws#group">Groups</a>. Members of a <a href="https://openjdk.org/bylaws#group">Group</a> collaborate on an area of mutual interest. The right hand side bar on the <a href="https://openjdk.org/">OpenJDK website</a> has a list of all <a href="https://openjdk.org/bylaws#group">Groups</a> in OpenJDK. If you’re interested in a specific area, this is where you would start your OpenJDK experience. Look at the <a href="https://openjdk.org/bylaws#group">Group’s</a> information and wiki pages, and see what <a href="https://openjdk.org/bylaws#project">Projects</a> they sponsor on the <a href="https://openjdk.org/census">Census page</a>. The <a href="https://openjdk.org/census">Census</a> shows the structure of the OpenJDK Community.</p> <p><a href="https://openjdk.org/bylaws#project">Projects</a> are where the coding and much of the other work is done in OpenJDK. There are many different <a href="https://openjdk.org/bylaws#project">Projects</a>, some produce shippable artifacts, like the <a href="https://openjdk.org/projects/jdk/">JDK Project</a>, some produce tools to be used by developers of these artifacts, like the <a href="https://openjdk.org/projects/code-tools/">Code Tools Project</a> or <a href="https://openjdk.org/projects/skara/">Project Skara</a>, and some produce documentation, like the <a href="https://openjdk.org/projects/guide/">Developers’ Guide Project</a>. Many <a href="https://openjdk.org/bylaws#project">Projects</a> designs and develops new features for the Java language or the JVM, but there are also less code centric ones like the <a href="https://openjdk.org/projects/duke/">Duke Project</a> which collects images of the Java mascot, Duke.</p> <h2 id="author-committer-reviewer">Author, Committer, Reviewer</h2> <p>OpenJDK has a few different roles that determine who has the right to do what in the different <a href="https://openjdk.org/bylaws#project">Projects</a>. These roles are defined in the <a href="https://openjdk.org/bylaws#project-roles">OpenJDK Bylaws</a>. The roles are earned based on experience and knowledge within each <a href="https://openjdk.org/bylaws#project">Project</a>.</p> <p>A <a href="https://openjdk.org/bylaws#contributor">Contributor</a> can have different roles in different <a href="https://openjdk.org/bylaws#project">Projects</a>. When you’re new to a <a href="https://openjdk.org/bylaws#project">Project</a> you don’t yet have a formal role in that specific <a href="https://openjdk.org/bylaws#project">Project</a>, even though you might have earned roles in other <a href="https://openjdk.org/bylaws#project">OpenJDK Projects</a> or have been recognized as a <a href="https://openjdk.org/bylaws#contributor">Contributor</a> or a <a href="https://openjdk.org/bylaws#openjdk-member">Member</a> of OpenJDK. By contributing high-quality content you’ll soon be eligible for <a href="https://openjdk.org/bylaws#project-roles">OpenJDK roles</a> in the <a href="https://openjdk.org/bylaws#project">Project</a>. First <a href="https://openjdk.org/bylaws#author">Author</a>, then <a href="https://openjdk.org/bylaws#committer">Committer</a>, and finally <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a> if you stay active and earn the trust of the community. Trust is an important part of earning these roles. There’s a <a href="https://openjdk.org/projects/">rough guideline</a> saying that to become a <a href="https://openjdk.org/bylaws#committer">Committer</a> you should have contributed 8 significant changes, and to become a <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a> you should have contributed 32 significant changes. In reality it’s not as easy as “just” contributing code. You need to build a track record of good decisions and sound judgment and show that you know what differentiates a good change from a not so good one. It’s not only correctness of the code that matters, it’s also the appropriateness. In the end the trust you’ve earned is put to the test through a vote.</p> <p>Note that when a new <a href="https://openjdk.org/bylaws#project">Project</a> is created an initial set of members can be brought in at different levels without a vote.</p> <h3 id="becoming-an-author">Becoming an Author</h3> <p>Becoming an <a href="https://openjdk.org/bylaws#author">Author</a> is the first step. To achieve this you need to contribute two changes to the <a href="https://openjdk.org/bylaws#project">Project</a> in which you wish to become an <a href="https://openjdk.org/bylaws#author">Author</a>. Once your changes are integrated into the code base and has been vetted enough to determine that the changes were indeed good changes you can go ahead and send an email to the Project lead of that particular <a href="https://openjdk.org/bylaws#project">Project</a> and ask to be added as an <a href="https://openjdk.org/bylaws#author">Author</a>. Note that “the <a href="https://openjdk.org/bylaws#project">Project</a>” is not OpenJDK, but rather the specific <a href="https://openjdk.org/bylaws#project">development Project</a> where you did your contributions (e.g. “JDK”, “JDK Updates”, “Amber”, etc). The <a href="https://openjdk.org/projects/#project-author">OpenJDK Project description</a> has a template for such an email. In short the email should contain your name, the Project name, your email address, and GitHub links to your changes. In response to your email you will get a time-limited invite which you should fill out.</p> <p>To see who the Project lead is for your <a href="https://openjdk.org/bylaws#project">Project</a>, see the <a href="https://openjdk.org/census">OpenJDK Census</a>. The <a href="https://openjdk.org/census">Census</a> unfortunately doesn’t provide email addresses for people, but assuming you have been active on the Project mailing list (since you are applying for <a href="https://openjdk.org/bylaws#author">Author</a> after all), you should be able to find the lead’s email address in your local email archive, or ask your <a href="https://openjdk.org/bylaws#sponsor">Sponsor</a>.</p> <p>As an <a href="https://openjdk.org/bylaws#author">Author</a> you will get your OpenJDK user name. Once you have gotten the user name, this should be associated with your GitHub account in order for the bots to be able to identify you on <a href="http://www.github.com">GitHub</a>. See the <a href="https://wiki.openjdk.org/display/SKARA#Skara-AssociatingyourGitHubaccountandyourOpenJDKusername"> Skara documentation</a> for more details on that. Once that’s done you can create PRs and get them reviewed, but you’ll still need a <a href="https://openjdk.org/bylaws#sponsor">Sponsor</a> to integrate changes. You’ll also get write access to <a href="#jbs---jdk-bug-system">JBS</a> and the <a href="https://wiki.openjdk.org">OpenJDK wiki</a> related to the <a href="https://openjdk.org/bylaws#project">Project</a> in question, and to <a href="https://cr.openjdk.org">cr.openjdk.org</a> via an SSH key provided at the time you accept your invitation.</p> <p>The rules of any particular <a href="https://openjdk.org/bylaws#project">Project</a> may have different guidelines regarding requirements for Authorship at the discretion of the Lead.</p> <h3 id="becoming-a-committer">Becoming a Committer</h3> <p>To become a <a href="https://openjdk.org/bylaws#committer">Committer</a> you should show that you intend to actively contribute to the <a href="https://openjdk.org/bylaws#project">Project</a> and that you can produce non-trivial changes that are accepted for inclusion into the Project code base. The number eight has been seen as a formal lower limit on the number of changes, but since the changes must be non-trivial, or “significant” as the <a href="https://openjdk.org/projects/">OpenJDK Project description</a> says, and the definition of significant is subjective, the general recommendation is to wait with a <a href="https://openjdk.org/bylaws#committer">Committer</a> nomination until there’s at least 10-12 changes integrated to have some margin for different interpretations of “significant”. In practice though, we have seen several examples where the number of significant changes hasn’t been the dominating factor in a <a href="https://openjdk.org/bylaws#committer">Committer</a> vote. A <a href="https://openjdk.org/bylaws#contributor">Contributor’s</a> work in another <a href="https://openjdk.org/bylaws#project">OpenJDK Project</a> may also be relevant for the vote. What the vote should ultimately test is the <a href="https://openjdk.org/bylaws#contributor">Contributor’s</a> commitment to the <a href="https://openjdk.org/bylaws#project">OpenJDK Project</a> for which the vote applies - is it believed that the person is dedicated and willing to spend time and effort on the <a href="https://openjdk.org/bylaws#project">Project</a>? Is the person believed to be a good citizen of the <a href="https://openjdk.org/bylaws#project">Project</a>? It’s always a good idea to seek the advice of a <a href="https://openjdk.org/bylaws#sponsor">Sponsor</a> who can guide you through the process to becoming a <a href="https://openjdk.org/bylaws#committer">Committer</a> - you will need one to run the Committer vote anyway. They will probably also have a better idea of what constitutes a “significant” change.</p> <p>Once you have the required changes, a <a href="https://openjdk.org/bylaws#committer">Committer</a> in the <a href="https://openjdk.org/bylaws#project">Project</a> can start a vote by sending an email proposing that you should become a <a href="https://openjdk.org/bylaws#committer">Committer</a>. The email should follow the template found in the <a href="https://openjdk.org/projects/#project-committer">OpenJDK Project description</a>.</p> <p>A <a href="https://openjdk.org/bylaws#committer">Committer</a> is allowed to integrate changes without the aid of a <a href="https://openjdk.org/bylaws#sponsor">Sponsor</a>. A <a href="https://openjdk.org/bylaws#committer">Committer</a> is also allowed to nominate other non-Committers to become <a href="https://openjdk.org/bylaws#committer">Committers</a> in the <a href="https://openjdk.org/bylaws#project">Project</a>.</p> <h3 id="becoming-a-reviewer">Becoming a Reviewer</h3> <p>To become a <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a> you must show a track record of sound and correct judgment calls as mentioned above. Being a good <a href="https://openjdk.org/bylaws#committer">Committer</a> doesn’t necessarily make you a good <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a>. As a <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a> you have the power to approve changes for inclusion into the Project source code. This means that a <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a> needs to be able to judge the quality and appropriateness of any proposed change, not just the mechanics of the code.</p> <p>The assumption is that after having produced 32 significant changes one should have become familiar with the process around reviews and the requirements around getting a change approved. This should really be seen as a minimum requirement though. A more practical consideration would be to look at whether the non-trivial commits of a potential <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a> are accepted largely intact or whether they are always being refined by the review process. There may be cases where it will take significantly more than 32 changes for a <a href="https://openjdk.org/bylaws#committer">Committer</a> to be ready to become a <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a>.</p> <p>Once you are deemed ready, a <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a> in the <a href="https://openjdk.org/bylaws#project">Project</a> can start a vote by sending an email proposing that you should become a <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a>. The email should follow the template found in the <a href="https://openjdk.org/projects/#project-reviewer">OpenJDK Project description</a>.</p> <h3 id="non-trivialsignificant-changes">Non-trivial/Significant changes</h3> <p>One key definition when advancing through the OpenJDK roles is the significant change. What exactly does it take for a change to be significant?</p> <p>Instead of describing the significant change (because that’s quite difficult to define) provided here is a few examples of changes that wouldn’t be considered significant or for other reasons wouldn’t count as significant contributions.</p> <ul> <li>Purely aesthetic changes like renaming or fixing indentation</li> <li>Repeated follow-up bugfixes from earlier changes</li> <li>Larger changes where only a non-significant portion of the work was done by the <a href="https://openjdk.org/bylaws#contributor">Contributor</a> under vote</li> <li>Trivial backports of someone else’s changes</li> </ul> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="contributing-to-an-openjdk-project">Contributing to an OpenJDK Project</h1> <p>Contributing to OpenJDK can take many forms. Writing code and providing patches is just one of them. A big part of developing a feature or a bugfix is testing and code review. Anything you can do to help out in these areas will be recognized as a contribution. Join the <a href="#mailing-lists">mailing lists</a> to engage in design discussions and reviews, and download the latest EA builds or Project repositories to try out new features and give feedback. If you see some misbehavior, or if you see somebody mention some misbehavior on some internet forum, try to track it down. Good bug reports with reproducible test cases are extremely valuable and make excellent contributions.</p> <p>Anything you can do to spread the word about Java, new features, and your experiences using the JDK will be helpful for the community and to the OpenJDK developers. Trying out a new feature and reporting your experiences is also a contribution. Whether you find that the new feature improves your application, or if you find some area that needs to be improved, your feedback is valuable to the developers of that feature.</p> <p>If you have a success story where Java solved your problem, or if you successfully upgraded to a more recent version of the JDK and noticed some improvements, spreading this story through a blog, news article, or some other channel is also a contribution.</p> <p>If you’re in a position to choose what programming language to use in a project, in a tutorial, or in a class, you have the power to enlarge the Java community in a very direct way, and your colleagues or students will get an opportunity to learn one of the most used programming languages in the world.</p> <h2 id="things-to-consider-before-proposing-changes-to-openjdk-code"> Things to consider before proposing changes to OpenJDK code</h2> <p>Every change to JDK code carries a risk of changes in behavior which may adversely affect applications. Generally we’re looking to improve the functionality and capability and sometimes performance of the platform without that negative consequence. So we need to ask ourselves whether each change is worthwhile - and some may not be no matter how well intentioned.</p> <p>One question to ask yourself is: <strong>What problem are you trying to solve?</strong></p> <p>The important thing here is to understand the problem itself, independent of any solution (and independently of the solution that currently happens to be in your change). A number of other questions and lines of thought emanate from thinking about the problem. For example: is this the right problem to solve? Does solving this problem create worse problems elsewhere; that is, is there a net benefit? Does this problem need to be solved in the JDK, or can and should it be solved elsewhere (e.g., in tooling)?</p> <p>The next question you need to answer before making any change is: <strong>What is the main intention of your change?</strong></p> <p>Depending on your answer to that question you will need to consider one or more of the following paragraphs.</p> <ul> <li> <p><strong>Correctness</strong> – If your change improves program correctness, that’s important. And to broaden this, fixing of all kinds of bugs that really make things better for applications in ways they can detect is important.</p> </li> <li> <p><strong>Robustness</strong> – Updating code to use a newer platform API can be a good change. Moving away from APIs that are being deprecated or that are no longer maintained is likely desired. Do note though that supposedly equivalent APIs may not be the drop in replacement you think they are. You’ll need to prove that the code has the same behavior after the change through extensive testing.</p> </li> <li> <p><strong>Security</strong> – If you intend to increase the overall security of the platform, changes following secure coding practices and using appropriate platform APIs for that are usually welcome. The exception might be if it’s a potentially destabilizing change in code where there’s only a theoretical problem. <strong>Please note</strong>: If you think you found a real security bug that might compromise the platform you should follow the process <a href="https://openjdk.org/groups/vulnerability/report">here</a>.</p> </li> <li> <p><strong>Refactoring / Cleanup</strong> – Making code easier to understand or reducing code size may be a good change in areas that are under active development. Stable code however isn’t a good candidate for refactoring regardless of what the code looks like. The OpenJDK has evolved over many years and some parts have been stable for decades. If there’s no immediate need to work on the code for other reasons, then what will a cleanup actually achieve? One specific area where refactoring and cleanups are explicitly discouraged is in third-party code.</p> </li> <li> <p><strong>Performance</strong> – Can you demonstrate a user perceptible change? If you can’t measure the change, or a user can’t notice the change, or the change only improves code that is used infrequently, then maybe it isn’t worth it. Do you have benchmarks to back up your claims? Do you understand the results? Performance testing is complex and often there are many factors unrelated to your change that affects the numbers. What’s the tradeoff? The performance improvements that just make everything better do exist, but they are extremely rare. Most often the code gets more complex, or you speed up one case but slow down another. Are you making the right tradeoff?</p> </li> <li> <p><strong>Modernizing</strong> – Changing code purely for the sake of using a new language feature isn’t usually a good change. Be a subject matter expert, not just a language expert. Writing code in “a better way” is not guaranteed to be safe. A change of behavior is always possible and unless you understand the code you are changing at more than the core language/API level, and have looked into appropriate tests and can speak to the risks, then you should first find a subject matter expert to discuss it with. Keep in mind that the OpenJDK code is developed by a large community. If a new language feature is introduced, all developers working in that code must learn this new feature and understand the implications of using it.</p> </li> </ul> <h2 id="i-have-a-patch-what-do-i-do">I have a patch, what do I do?</h2> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://www.oracle.com/technical-resources/oracle-contributor-agreement.html"> Oracle Contributor Agreement (OCA)</a></li> <li><a href="https://oca.opensource.oracle.com/?ojr=contrib-list">OCA Signatories List</a></li> <li><a href="https://openjdk.org/legal/">OpenJDK Legal Documents</a></li> <li><a href="https://bugs.openjdk.org/">JDK Bug System (JBS)</a></li> <li><a href="https://openjdk.org/bylaws#project-roles">OpenJDK Project Roles</a></li> </ul> </div> <p>In many GitHub projects the standard way to propose a change is to create a pull request (PR) and discuss the patch in the PR. For <a href="https://openjdk.org/bylaws#project">OpenJDK Projects</a> the situation is somewhat different. The JDK is used for mission critical applications and by millions of developers, the bar to contributing changes is high. Please follow the steps outlined below to make sure your change passes above the bar before creating a PR.</p> <h3 id="sign-the-oca">1. Sign the OCA</h3> <p>Like many other open-source communities, the OpenJDK Community requires Contributors to jointly assign their copyright on contributed code. <a href="https://www.oracle.com">Oracle</a> is the steward of OpenJDK and if you haven’t yet signed the <a href="https://oca.opensource.oracle.com/">Oracle Contributor Agreement</a> (OCA), and are not covered by a company-level agreement, then please do so. This is required in order to make your patch available for review. The OCA gives <a href="https://www.oracle.com">Oracle</a> and you as a Contributor joint copyright interests in the code. You will retain your copyright while also granting those rights to <a href="https://www.oracle.com">Oracle</a>. If you don’t know if your organization has signed the OCA you can check the <a href="https://oca.opensource.oracle.com/?ojr=contrib-list">OCA Signatories List</a>, or ask your legal advisor.</p> <p>When you sign the OCA, please make sure that you specify your GitHub user name in the <code>Username</code> field of the OCA. If you try to create a PR before you have signed the OCA, or if you didn’t specify your GitHub user name, you’ll get instructions telling you to do so, and the PR won’t be published until this is done. OCA registration is a manual process. Please allow for up to several days to have your OCA application processed, even though it’s normally processed swiftly. An alphabetical list of all of the assigned OpenJDK usernames can be found on the <a href="https://db.openjdk.org/people">OpenJDK people</a> list.</p> <p>You only need to sign the OCA once in order to cover all changes that you might contribute to any Oracle-sponsored open-source community. If you’ve already signed the OCA or the former SCA (Sun Contributor Agreement) for any Oracle-sponsored open-source community, then you do not need to sign it again in order to contribute to OpenJDK. Please note that you don’t need to sign an OCA if you work at Oracle or a company which has negotiated an equivalent agreement.</p> <h3 id="socialize-your-change">2. Socialize your change</h3> <p>Once the OCA is signed, please restrain your urge to create a PR just a little while longer. In order to prepare the community for your patch, please socialize your idea on the relevant <a href="#mailing-lists">mailing lists</a>. Almost all changes, and in particular any API changes, must go this route and have a broad agreement in place before there is any point in presenting code. To understand the criteria by which your patch is going to be judged, please read <a href="#why-is-my-change-rejected">Why is My Change Rejected?</a> below. In short, hidden constraints and assumptions, stability and quality, maintainability, compatibility, and conformance to specifications must be considered before your PR is ready to be submitted. If you don’t understand the constraints for acceptance, you might be surprised when your PR is rejected.</p> <h3 id="find-a-sponsor">3. Find a Sponsor</h3> <p>Socializing your change on the mailing lists also prevents the surprise that would otherwise make the community choke on their morning coffee when they see a huge patch in a new, unknown PR. As a new developer in the community you’ll need to make a few friends that agree with your change. There are many good reasons to make friends, but the one relevant here is that for your first changes you’ll need a <a href="https://openjdk.org/bylaws#sponsor">Sponsor</a> to facilitate the integration of your work. The <a href="https://openjdk.org/bylaws#sponsor">Sponsor</a> will perform any number of administrative tasks like JBS updates, additional testing, etc. It’s usual for a <a href="https://openjdk.org/bylaws#sponsor">Sponsor</a> to also be a reviewer of a change and thus familiar with it, but it’s not a requirement.</p> <h3 id="create-a-tracking-issue-in-jbs">4. Create a tracking issue in JBS</h3> <p>Many <a href="https://openjdk.org/bylaws#project">OpenJDK Projects</a> require a tracking issue to be filed in the <a href="https://bugs.openjdk.org/">JDK Bug System (JBS)</a> before a change can be integrated. This is the case for instance for the JDK and the JDK Updates Projects. In order to obtain write access to JBS you need to be an <a href="https://openjdk.org/bylaws#author">Author</a> in an <a href="https://openjdk.org/bylaws#project">OpenJDK Project</a> (see <a href="#becoming-an-author">Becoming an Author</a>). For your first changes, ask your <a href="https://openjdk.org/bylaws#sponsor">Sponsor</a> to help you create the issue or file the bug through the <a href="https://bugreport.java.com/">Bug Report Tool</a>.</p> <h3 id="get-acquainted-with-local-process">5. Get acquainted with local process</h3> <p>Even though we strive to unify how things are done within OpenJDK, different areas and <a href="https://openjdk.org/bylaws#project">Projects</a> in OpenJDK may have slight variations in how they work. Some of these differences are highlighted throughout this guide, some aren’t. If you’re new to an area, make sure you understand local differences before you proceed. Ask your <a href="https://openjdk.org/bylaws#sponsor">Sponsor</a> who should be your main point of contact through your first developer experience in OpenJDK.</p> <h2 id="why-is-my-change-rejected">Why is my change rejected?</h2> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://docs.oracle.com/javase/specs/">Java Language and Virtual Machine Specifications</a></li> <li><a href="https://docs.oracle.com/en/java/javase/15/docs/api/index.html">Java API Specification</a></li> <li><a href="https://wiki.openjdk.org/display/csr/Main">CSR Process</a></li> </ul> </div> <p>Just about every Java developer out there has an idea or two for how to enhance something. And believe it or not, not every idea is a good idea. Even though many ideas are indeed good, we must be quite restrictive on what we actually include into the JDK. The goal is not to take in the maximum number of contributions possible, but rather to accept only the highest-quality contributions. The JDK is used daily by millions of people and thousands of businesses, often in mission-critical applications, and so every change must be scrutinized in detail. There are many reasons for this.</p> <ul> <li> <p><strong>Hidden constraints and assumptions</strong> – Many sections of code have constraints and assumptions that aren’t necessarily visible at first glance. This might preclude certain changes, even those that might seem obvious.</p> </li> <li> <p><strong>Stability and quality</strong> – The JDK is used by millions of developers and as a widely deployed commercial product, it’s held to a high standard of quality. Changes should include tests where practical, and core tests should pass at all times. The value of the change should outweigh the risk of introducing a bug or performance regression.</p> </li> <li> <p><strong>Maintainability</strong> – Any new feature or code change will need to be maintained in the JDK essentially forever, thus imposing a maintenance burden on future maintainers. The code might still be in use long after you and the people who reviewed it have moved on. New maintainers must be able to understand how to fix bugs in this code.</p> </li> <li> <p><strong>Complexity</strong> – Each new feature interacts with all the existing features, which can result in geometric growth of the interactions among features if features are added unchecked. Sometimes we avoid adding a new feature, even if it seems like an obvious thing to add, if that feature would make it difficult to add a more important feature in the future.</p> </li> <li> <p><strong>Adherence to specifications</strong> – Much of the JDK is governed by a series of specifications, in particular the <a href="https://docs.oracle.com/javase/specs/">Java Language Specification</a>, the <a href="https://docs.oracle.com/javase/specs/">Java Virtual Machine Specification</a>, and the <a href="https://docs.oracle.com/en/java/javase/15/docs/api/index.html">Java API Specification</a> (“javadocs”). All changes must be checked and tested carefully to ensure that they don’t violate these specifications.</p> </li> <li> <p><strong>Javadoc comments are specifications</strong> – The Java API Specification is authored in the form of javadoc comments, so even apparently innocuous changes to comments can be quite significant. It’s not always easy to tell what comments are part of the specification and what parts are merely code comments. Briefly, documentation comments on public packages, classes, and class members of exported modules are specifications.</p> </li> <li> <p><strong>Specification changes</strong> – It’s possible to change the API specifications, and this is done regularly. However, these changes require even more scrutiny than code changes. This extra review is handled by the <a href="https://wiki.openjdk.org/display/csr/Main">CSR Process</a>. Specifications are written in stylized, somewhat formal language, and they don’t simply describe what the code does. Writing specifications is a separate skill from coding.</p> </li> <li> <p><strong>Compatibility</strong> – Changes should also adhere to high standards of binary, source, and behavioral compatibility. The compatibility impact of apparently innocuous changes is sometimes startling.</p> </li> </ul> <p>For reasons like these it’s quite possible that your change, even though it adds value to you, isn’t deemed to add enough value to the larger community.</p> <p>If you’re relatively new to the Java platform then we recommend that you gain more experience writing Java applications before you attempt to work on the JDK itself. The purpose of the sponsored-contribution process is to bring developers who already have the skills required to work on the JDK into the existing development community. The members of this community have neither the time nor the patience required to teach basic Java programming skills or platform implementation techniques.</p> <p>The feature releases currently under development are in the JDK Project. Most development work is focused on the newest release, so generally you should be working against the latest JDK sources rather than the JDK Updates sources.</p> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="mailing-lists">Mailing Lists</h1> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://mail.openjdk.org/mailman/listinfo">OpenJDK Mailing Lists Manager</a></li> </ul> </div> <p>The mailing lists are the key communications mechanism for all OpenJDK work. All participation in an <a href="https://openjdk.org/bylaws#project">OpenJDK Project</a> starts with joining the relevant mailing list. A subscriber to an OpenJDK mailing list is referred to as a <a href="https://openjdk.org/bylaws#participant">Participant</a> in the <a href="https://openjdk.org/bylaws">Bylaws</a>. As a general recommendation we suggest to subscribe to <a href="https://mail.openjdk.org/mailman/listinfo/announce">announce</a>, <a href="https://mail.openjdk.org/mailman/listinfo/discuss">discuss</a>, and the <code>-dev</code> lists covering your explicit area of interest. All OpenJDK mailing lists are found here:</p> <blockquote> <p><a href="https://mail.openjdk.org/mailman/listinfo"><code>mail.openjdk.org</code></a></p> </blockquote> <div class="note"> <p>Please note that OpenJDK mailing lists typically are for discussions about the <strong>development</strong> of the JDK, not its usage. This is not a place to ask support questions. If you think you found an issue in or with the JDK, see <a href="#jbs---jdk-bug-system">JBS - JDK Bug System</a> for instructions on reporting it.</p> </div> <p>The OpenJDK Community is a friendly place. To keep it that way it’s important to keep a professional tone in emails and be aware that the community is global. Many different people with different backgrounds collaborate in these lists. Even though English is the required language for all lists, many Participants speak other languages as their native language. A high tolerance for non-perfect English is expected from anyone joining these lists. You’re also strongly encouraged to use your real name on the mailing lists. This adds to the professional tone of your email. Postings from anonymized mailboxes risk being seen as spam. If you do work in OpenJDK on behalf of your employer, please also list this affiliation. If your GitHub username differs from your real name it’s also a good idea to include that to identify yourself and your actions on <a href="https://github.com">GitHub</a>.</p> <p>You must be a member of a list to be able to post to that list. Some lists are moderated to keep the content on topic. Each list has its own archive where you can browse older conversations on the list.</p> <p>There are a few different types of lists. The list name has two parts to explain what the list is intended for, <code><name>-<suffix></code>. The name often refers to the <a href="https://openjdk.org/bylaws#project">Project</a> that owns the list or a specific area of interest that the list focuses on. The suffix is explained below. Not all <a href="https://openjdk.org/bylaws#project">Projects</a> or areas have all types of lists described here.</p> <blockquote> <dl> <dt><code>-dev</code></dt> <dd>Technical discussions around the implementation of the Project artifacts. This is also where code reviews happen.</dd> </dl> </blockquote> <blockquote> <dl> <dt><code>-use</code></dt> <dd>Technical discussions around the usage of the Project artifacts.</dd> </dl> </blockquote> <blockquote> <dl> <dt><code>-discuss</code></dt> <dd>General discussions around the <a href="https://openjdk.org/bylaws#project">Project</a>. The special case <code>discuss@openjdk.org</code> is used for general discussions around OpenJDK. Discussions around new Project proposals usually happen here.</dd> </dl> </blockquote> <blockquote> <dl> <dt><code>-changes</code></dt> <dd>Changeset notifications from the source code repositories maintained by the <a href="https://openjdk.org/bylaws#project">Project</a>.</dd> </dl> </blockquote> <blockquote> <dl> <dt><code>-announce</code></dt> <dd>General Project announcements. These lists are tightly moderated and are expected to be low traffic. The special case <code>announce@openjdk.org</code> is used for announcements for OpenJDK.</dd> </dl> </blockquote> <blockquote> <dl> <dt><code>-experts</code></dt> <dd>Expert group discussions. The list is restricted; only members of the expert group can subscribe.</dd> </dl> </blockquote> <blockquote> <dl> <dt><code>-observers</code></dt> <dd>Open for anyone to subscribe to see what the experts are discussing and potentially to have some dialog with other non-experts. There is no guarantee that an expert is subscribed to the <code>-observers</code> list or will see any responses on that list.</dd> </dl> </blockquote> <blockquote> <dl> <dt><code>-comments</code></dt> <dd>Used by observers to directly provide feedback/comments to the experts (typically a lead will process the comments list and forward things on to the experts list).</dd> </dl> </blockquote> <h2 id="changing-your-email-address">Changing your email address</h2> <p>If you need to change your registered email address, or if you have any other problems with the mailing lists, please contact <a href="mailto:mailman@openjdk.org">mailman@openjdk.org</a>.</p> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="code-conventions">Code Conventions</h1> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://www.oracle.com/technetwork/java/codeconvtoc-136057.html">Java Code Conventions</a></li> <li><a href="https://github.com/openjdk/jdk/blob/master/doc/hotspot-style.md">HotSpot C++ Code Conventions</a></li> </ul> </div> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="jbs---jdk-bug-system">JBS - JDK Bug System</h1> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://bugreport.java.com/">Bug Report Tool</a></li> <li><a href="https://bugs.openjdk.org/">JDK Bug System (JBS)</a></li> </ul> </div> <p><a href="https://bugs.openjdk.org/">JBS</a> is a public issue tracker used by many <a href="https://openjdk.org/bylaws#project">OpenJDK Projects</a> and is open for anyone to read and search. To get write access you need to be registered in the <a href="https://openjdk.org/census">OpenJDK Census</a> by becoming, for instance, an <a href="https://openjdk.org/bylaws#author">Author</a> in an <a href="https://openjdk.org/bylaws#project">OpenJDK Project</a>.</p> <h2 id="filing-an-issue">Filing an issue</h2> <p>When a new failure is found, or an improvement identified, an issue should be filed to describe and track its resolution. Depending on your role in OpenJDK you can either use the <a href="https://bugreport.java.com/">Bug Report Tool</a> or, if you are registered in the <a href="https://openjdk.org/census">OpenJDK Census</a>, you can report the issue directly in <a href="https://bugs.openjdk.org/">JBS</a>.</p> <p>When filing an issue, try to make the report as complete as possible in order to make it easier to triage, investigate and resolve the issue. Bug descriptions and comments should be written in a professional manner.</p> <div class="note"> <p>If you suspect that the issue is a vulnerability, <strong>don’t file a JBS issue!</strong> Instead send your report to <a href="mailto:vuln-report@openjdk.org">vuln-report@openjdk.org</a>. Also use this alias if you find an existing report which may cover a vulnerability - please do <em>not</em> report or discuss potential vulnerabilities on any open lists or other public channels - see <a href="https://openjdk.org/groups/vulnerability/report">OpenJDK Vulnerabilities</a> for more information.</p> </div> <p>A few things to keep in mind when filing an issue:</p> <ul> <li>Before filing, verify that there isn’t an open issue already filed. <ul> <li>Search <a href="https://bugs.openjdk.org/">JBS</a> for things like the name of the failing test, assert messages, the name of the source code file where a crash occurred etc.</li> <li>If you find a similar issue that was closed as <span class="jbs-value">Cannot Reproduce</span> then it may be appropriate to re-open that one - if you don’t have direct access to JBS you can file a bug using the <a href="https://bugreport.java.com/">Bug Report Tool</a> requesting that it be reopened.</li> </ul> </li> <li>Make a reasonable attempt to narrow down which build or release the failure first appeared in.</li> <li>Set <span class="jbs-field">Affects Version/s</span> to the earliest JDK version where the failure was seen. <ul> <li>If the failure is found in an update train of the JDK (e.g. 11.0.x), please see (if possible) if it’s also present in <a href="https://github.com/openjdk/jdk">mainline</a>. See <a href="#indicating-what-releases-an-issue-is-applicable-to">Indicating what releases an issue is applicable to</a> for more details.</li> <li>All issues of type <span class="jbs-value">Bug</span> must have the <span class="jbs-field">Affects Version/s</span> set. It’s not a bug if it doesn’t affect some version.</li> <li>For enhancements the <span class="jbs-field">Affects Version/s</span> should be left empty, unless it is only relevant to a specific release family.</li> </ul> </li> <li>Add relevant <span class="jbs-field">Labels</span> like <a href="#intermittent"><span class="jbs-label">intermittent</span></a>, <a href="#regression"><span class="jbs-label">regression</span></a>, <a href="#noreg-self"><span class="jbs-label">noreg-self</span></a>, <a href="#tier"><span class="jbs-label">tier1</span></a> etc. <ul> <li>For more information see the <a href="#jbs-label-dictionary">JBS Label Dictionary</a>.</li> </ul> </li> <li>Set the priority. <ul> <li>It’s not the reporter’s responsibility to set a correct priority, this will be done later in <a href="#triaging-an-issue">triage</a>, but a qualified guess is always better than the default. In JBS the range of priorities go from P1 (High/Important) to P5 (Very Low/Not Important), with the default being P4.</li> <li>If you have a sense that the issue is critical, or not critical at all, then adjusting the priority higher or lower makes sense, otherwise you can leave it as the default.</li> <li>When setting the priority, consider things like how the bug impacts the product and our testing, how likely is it that the bug is triggered, how difficult is it to work around, and whether it’s a regression, since that may break existing applications. Regressions are often higher priority than long-standing bugs and may block a release if not fixed. An example of a P1 would be an issue that is blocking a build or a release, whereas a P5 would be a minor typo in a code comment.</li> </ul> </li> <li>In the <span class="jbs-field">Description</span>, always include (if possible): <ul> <li>error messages</li> <li>assert messages</li> <li>stack trace</li> <li>command line information</li> <li>relevant information from the logs</li> <li>full name of any failing tests</li> </ul> </li> <li>Avoid including in the report: <ul> <li>personal information</li> <li>passwords, logins, machine names</li> <li>logs which may include sensitive data</li> <li>large amount of text or data - large logfiles are better provided as attachments</li> </ul> </li> <li>If the failure isn’t reproducible with an existing OpenJDK test, attach a reproducer if possible, having a test case will decrease the time required to resolve the issue.</li> <li>In general the <span class="jbs-field">CPU</span> and/or <span class="jbs-field">OS</span> fields should not be set. <strong>ONLY</strong> use them if you know that the issue is only relevant to a particular platform or set of platforms.</li> <li>Provide the output of <code>java -version</code> whenever possible - this version information is particularly critical for hangs, JVM bugs, and network issues.</li> <li>Always file separate bugs for different issues. <ul> <li>If two crashes look related, but not similar enough to be sure they are the same, it’s easier to later close a bug as a duplicate than it is to separate out one bug into two.</li> </ul> </li> </ul> <h3 id="types-of-issues">Types of issues</h3> <p>The most common issue types are:</p> <table> <colgroup> <col width="15%" /> <col width="84%" /></colgroup> <thead> <tr class="header"> <th align="left">Issue Type</th> <th align="left">Covers</th> </tr> </thead> <tbody> <tr class="odd"> <td align="left"><span class="jbs-value">Bug</span></td> <td align="left">A <span class="jbs-value">Bug</span> should relate to functional correctness - a deviation from behavior that can be tied back to a specification. Anything else, including performance concerns, is generally not a bug, but an enhancement. Though it’s not clear-cut as a significant performance regression may be classified as a <span class="jbs-value">Bug</span>, for example.</td> </tr> <tr class="even"> <td align="left"><span class="jbs-value">Enhancement</span></td> <td align="left">An <span class="jbs-value">Enhancement</span> is a small to medium improvement to existing functionality.</td> </tr> <tr class="odd"> <td align="left"><span class="jbs-value">JEP</span></td> <td align="left">The <span class="jbs-value">JEP</span> issue type is used for a proposal of a significant change or new feature which will take four or more weeks of work - see <a href="https://openjdk.org/jeps/1">JEP-1</a>.</td> </tr> <tr class="even"> <td align="left"><span class="jbs-value">Sub-task</span></td> <td align="left">Sub-tasks can be used to break up the work for an issue, such as the changes to the docs, tests etc. This is not recommended as a way to break up a large amount of code change associated with a new feature - see <a href="#implementing-a-jep">Implementing a JEP</a> or <a href="#implementing-a-large-change">Implementing a large change</a> below.</td> </tr> <tr class="odd"> <td align="left"><span class="jbs-value">Task</span></td> <td align="left">Tasks are used to track work that isn’t expected to result in a change in any code repository. They are used for related activities such as a new JBS version number, a build request, an update to a document etc.</td> </tr> <tr class="even"> <td align="left"><span class="jbs-value">New Feature</span></td> <td align="left">Not recommended for use.</td> </tr> </tbody> </table> <div class="note"> <p>A <span class="jbs-value">Bug</span> or <span class="jbs-value">Enhancement</span> should only be used if the work is expected to result in a change in a code repository. A <span class="jbs-value">Bug</span> or <span class="jbs-value">Enhancement</span> with resolution <span class="jbs-value">Fixed</span> is required to have a corresponding changeset in one of the OpenJDK repositories.</p> </div> <h3 id="indicating-what-releases-an-issue-is-applicable-to"> Indicating what releases an issue is applicable to</h3> <p>Knowing when an issue was introduced is important to determine the impact of the issue and where it needs to be resolved. While in some cases it may be clear, it is likely that on submission and during triage this won’t be known, instead we will have one or two data points from which we can begin to understand the range of releases which the issue impacts.</p> <p>The <span class="jbs-field">Affects Version/s</span> field is used to indicate which releases an issue is applicable to, and to avoid having to set it to an exhaustive list of impacted releases the following assumptions are used to give that range:</p> <ol style="list-style-type: decimal"> <li>If an issue is applicable to a feature release N, it is assumed to be applicable to all (more recent) releases unless indicated otherwise (see <a href="#usage-of-the-rel-na-label">(Rel)-na</a> below). <ul> <li>Note that if it’s reported against an update release then all we can say is that it’s applicable to all the following update releases, not necessarily the next feature release as it may have been introduced in an update. Given this, it is always important to try and reproduce the issue in the corresponding feature release as well as mainline.</li> </ul> </li> <li>If an issue is applicable to release N, then it can’t be assumed that it is applicable to older releases less than N. It may be, but in general this is less important to know, as the majority of issues are only fixed in the latest feature release. If the issue is a crash or important in another way, then it becomes worthwhile to take the time to determine if it’s relevant to earlier LTS releases.</li> </ol> <p>Another aspect of an issue is when the feature it’s a part of was added or removed from the JDK, which in either case limits the range of releases the issue impacts. Knowing that a feature was removed before the oldest currently maintained release means it can be resolved as <span class="jbs-value">Won’t Fix</span>.</p> <h4 id="setting-the-affects-versions-field">Setting the Affects Version/s field</h4> <div class="note"> <p>Note that the <span class="jbs-field">Affects Version/s</span> field is mainly used for bugs and bug-like tasks/sub-tasks etc. In general enhancements and enhancement-like tasks/sub-tasks should not have an <span class="jbs-field">Affects Version/s</span>.</p> </div> <p>Set the <span class="jbs-field">Affects Version/s</span> field to the lowest release where the bug has been seen.</p> <ul> <li>The <span class="jbs-field">Affects Version/s</span> isn’t meant to be an exhaustive list of releases the issue is relevant to - it should initially be set to the release the issue was reproduced or identified on, and by implication it will be relevant to all releases past that point (see <a href="#usage-of-rel-na-label">Usage of the (Rel)<span class="jbs-label">-na</span> Label</a>). If it’s later found to be applicable to an earlier release family then adding that earlier release is encouraged if the issue needs to be fixed in that release.</li> <li>Don’t add additional release values to <span class="jbs-field">Affects Version/s</span> for the same release family. For example, if there is the value <span class="jbs-value">11.0.2</span>, don’t add <span class="jbs-value">11.0.5</span>, <span class="jbs-value">11.0.7</span> etc. Adding an additional value for a separate release family where it’s still reproducible, e.g. JDK <span class="jbs-value">21</span>, is encouraged if there isn’t currently a feature release value set, or, it has been a few releases since it was last reproduced/reviewed. For example, if the <span class="jbs-field">Affects Version/s</span> is JDK <span class="jbs-value">8</span>, but it is still relevant to the latest mainline release.</li> </ul> <h4 id="usage-of-the-rel-na-label">Usage of the (Rel)-na Label</h4> <p>Labels of the form (Rel)<span class="jbs-label">-na</span> (eg. <span class="jbs-label">17-na</span>) should be used when a bug is not applicable to a more recent release family. For example:</p> <p><span class="jbs-field">Affects Version/s</span>: <span class="jbs-value">7u111</span>, <span class="jbs-value">8u131</span></p> <p>add the label <span class="jbs-label">9-na</span> if the issue is not relevant to JDK 9 and above. Reasons why this would be the case include the fact that the source has been removed from a later release or rewritten such that the issue is no longer relevant.</p> <p>Don’t:</p> <ul> <li> <p>use the label to indicate that a bug is not relevant to an earlier release, for example</p> <p><span class="jbs-field">Affects Version/s</span>: <span class="jbs-value">11.0.20</span>, <span class="jbs-value">17</span></p> <p>the label <span class="jbs-label">8-na</span> would not be needed - as it doesn’t have a JDK 8 release, or earlier, value in the <span class="jbs-field">Affects Version/s</span>, it is not relevant to JDK 8. Also see <a href="#usage-of-rel-wnf-label">Usage of the (Rel)<span class="jbs-label">-wnf</span> Label</a></p> </li> <li> <p>add multiple <span class="jbs-label">-na</span> labels: you only need one, for example don’t add both <span class="jbs-label">9-na</span> and <span class="jbs-label">11-na</span> — <span class="jbs-label">9-na</span> implies all following releases therefore <span class="jbs-label">11-na</span>, or <span class="jbs-label">17-na</span> etc. are not needed.</p> </li> <li> <p>It’s not recommended to specify update releases like 17u4 or 21u in the label. Labels like <span class="jbs-label">17-na</span> and <span class="jbs-label">21-na</span> are in general enough.</p> </li> </ul> <h4 id="usage-of-the-rel-wnf-label">Usage of the (Rel)-wnf Label</h4> <p>Labels of the form (Rel)<span class="jbs-label">-wnf</span> (e.g. <span class="jbs-label">11-wnf</span>) should be used to indicate that a bug is not going to be fixed in a release that it’s applicable to, or any earlier releases. For example, <span class="jbs-label">11-wnf</span> states it won’t be fixed in JDK 11 and implicitly indicates it won’t be fixed in JDK 8 either.</p> <p>Add a comment when adding a (Rel)<span class="jbs-label">-wnf</span> label so that it’s clear for those looking at the issue, why it won’t be fixed in that release.</p> <h4 id="examples">Examples</h4> <div class="figure"><img src="affects_versions.png" alt="" /> <p class="caption">Guidelines for setting <span class="jbs-field">Affects Version/s</span></p> </div> <ol style="list-style-type: decimal"> <li>Issue relevant to JDK 8 and all future releases.</li> <li>No need to add additional releases as they are implied.</li> <li>Adding the occasional LTS release value is ok.</li> <li>Use N-na to indicate that the issue is no longer relevant from that release, which could be due to the feature or platform being removed or the code being rewritten.</li> <li>Use N-wnf to indicate that a fix will not be backported to that release, or earlier.</li> </ol> <h3 id="things-to-keep-in-mind-when-requesting-an-improvement"> Things to keep in mind when requesting an improvement</h3> <p>Unlike reporting a problem, when it comes to improvements, what constitutes a reasonable request can take discussion, and in general it’s encouraged that the <a href="#mailing-lists">mailing list</a> for the area is used to suggest an improvement before filing.</p> <p>Enhancements to the Java Language Specification and the JVM Specification are managed through the <a href="http://jcp.org/">Java Community Process</a>.</p> <p>To find out which component to use for different bugs, consult the <a href="#directory-to-area-mapping">directory to area mapping</a>.</p> <h3 id="implementing-a-large-change">Implementing a large change</h3> <p>When managing the work for a large change, especially when the work involves multiple engineers, it’s recommended that the work is distributed across one or more “implementation” issues which should be linked to the main enhancement with a “blocks” link along with any relevant CSRs. The enhancement shouldn’t be considered done until all the blocking elements are completed. The use of sub-tasks for enhancements is not recommended unless all the sub-tasks are relevant to the fix, if it were to be backported, for example <a href="https://bugs.openjdk.org/browse/JDK-8231641">JDK-8231641</a> or <a href="https://bugs.openjdk.org/browse/JDK-8171407">JDK-8171407</a>.</p> <h3 id="implementing-a-jep">Implementing a JEP</h3> <p>It’s recommended for <span class="jbs-value">JEP</span>s that the implementation is spread across one or more <span class="jbs-value">Enhancement</span>s as described above.</p> <h2 id="issue-states">Issue states</h2> <p>JBS only has a few states in which a <span class="jbs-value">Bug</span> or <span class="jbs-value">Enhancement</span> can be:</p> <table> <colgroup> <col width="15%" /> <col width="84%" /></colgroup> <thead> <tr class="header"> <th align="left">Type</th> <th align="left">Covers</th> </tr> </thead> <tbody> <tr class="odd"> <td align="left"><span class="jbs-value">New</span></td> <td align="left">Initial state after an issue is filed. Bugs in the JDK Project must be taken out of the <span class="jbs-value">New</span> state (“Triaged” - see below) in a timely manner. In general, triaging is recommended to be done for all issue types and projects as a sign that the issue is correctly filed, and will be seen by the right developers - this is especially important towards the end of a release.</td> </tr> <tr class="even"> <td align="left"><span class="jbs-value">Open</span></td> <td align="left">Once the issue has been triaged it will be in the <span class="jbs-value">Open</span> state and will stay here until an assignee decides to work on it, at which point it’s encouraged that the “Start Work” option be selected to move it to <span class="jbs-value">In Progress</span>.</td> </tr> <tr class="odd"> <td align="left"><span class="jbs-value">In Progress</span></td> <td align="left">The <span class="jbs-value">In Progress</span> state is used to show that the assignee is actively working on the issue. It has the optional sub-states (<span class="jbs-field">Understanding</span>): <span class="jbs-value">Cause Known</span>, <span class="jbs-value">Fix Understood</span>, <span class="jbs-value">In Review</span>.</td> </tr> <tr class="even"> <td align="left"><span class="jbs-value">Resolved</span></td> <td align="left">When the issue has been fixed it is <span class="jbs-value">Resolved</span> using the Resolve action in JBS.</td> </tr> <tr class="odd"> <td align="left"><span class="jbs-value">Closed</span></td> <td align="left">To finally close an issue it also needs to be verified using the issue’s regression test.</td> </tr> </tbody> </table> <div style="text-align:center;"> <div class="figure"><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibWVybWFpZC0xNzM4MTkwNjUzNjEyIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgaGVpZ2h0PSI3MjEiIHN0eWxlPSJtYXgtd2lkdGg6IDUzNi40OTJweDsgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7IiB2aWV3Qm94PSIwIDAgNTM2LjQ5MjE4NzUgNzIxIj48c3R5bGU+I21lcm1haWQtMTczODE5MDY1MzYxMiB7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O2ZpbGw6IzAwMDAwMDt9I21lcm1haWQtMTczODE5MDY1MzYxMiAuZXJyb3ItaWNvbntmaWxsOiM1NTIyMjI7fSNtZXJtYWlkLTE3MzgxOTA2NTM2MTIgLmVycm9yLXRleHR7ZmlsbDojNTUyMjIyO3N0cm9rZTojNTUyMjIyO30jbWVybWFpZC0xNzM4MTkwNjUzNjEyIC5lZGdlLXRoaWNrbmVzcy1ub3JtYWx7c3Ryb2tlLXdpZHRoOjJweDt9I21lcm1haWQtMTczODE5MDY1MzYxMiAuZWRnZS10aGlja25lc3MtdGhpY2t7c3Ryb2tlLXdpZHRoOjMuNXB4O30jbWVybWFpZC0xNzM4MTkwNjUzNjEyIC5lZGdlLXBhdHRlcm4tc29saWR7c3Ryb2tlLWRhc2hhcnJheTowO30jbWVybWFpZC0xNzM4MTkwNjUzNjEyIC5lZGdlLXBhdHRlcm4tZGFzaGVke3N0cm9rZS1kYXNoYXJyYXk6Mzt9I21lcm1haWQtMTczODE5MDY1MzYxMiAuZWRnZS1wYXR0ZXJuLWRvdHRlZHtzdHJva2UtZGFzaGFycmF5OjI7fSNtZXJtYWlkLTE3MzgxOTA2NTM2MTIgLm1hcmtlcntmaWxsOiM2NjY7c3Ryb2tlOiM2NjY7fSNtZXJtYWlkLTE3MzgxOTA2NTM2MTIgLm1hcmtlci5jcm9zc3tzdHJva2U6IzY2Njt9I21lcm1haWQtMTczODE5MDY1MzYxMiBzdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O30jbWVybWFpZC0xNzM4MTkwNjUzNjEyIC5sYWJlbHtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Y29sb3I6IzAwMDAwMDt9I21lcm1haWQtMTczODE5MDY1MzYxMiAuY2x1c3Rlci1sYWJlbCB0ZXh0e2ZpbGw6IzMzMzt9I21lcm1haWQtMTczODE5MDY1MzYxMiAuY2x1c3Rlci1sYWJlbCBzcGFue2NvbG9yOiMzMzM7fSNtZXJtYWlkLTE3MzgxOTA2NTM2MTIgLmxhYmVsIHRleHQsI21lcm1haWQtMTczODE5MDY1MzYxMiBzcGFue2ZpbGw6IzAwMDAwMDtjb2xvcjojMDAwMDAwO30jbWVybWFpZC0xNzM4MTkwNjUzNjEyIC5ub2RlIHJlY3QsI21lcm1haWQtMTczODE5MDY1MzYxMiAubm9kZSBjaXJjbGUsI21lcm1haWQtMTczODE5MDY1MzYxMiAubm9kZSBlbGxpcHNlLCNtZXJtYWlkLTE3MzgxOTA2NTM2MTIgLm5vZGUgcG9seWdvbiwjbWVybWFpZC0xNzM4MTkwNjUzNjEyIC5ub2RlIHBhdGh7ZmlsbDojZWVlO3N0cm9rZTojOTk5O3N0cm9rZS13aWR0aDoxcHg7fSNtZXJtYWlkLTE3MzgxOTA2NTM2MTIgLm5vZGUgLmxhYmVse3RleHQtYWxpZ246Y2VudGVyO30jbWVybWFpZC0xNzM4MTkwNjUzNjEyIC5ub2RlLmNsaWNrYWJsZXtjdXJzb3I6cG9pbnRlcjt9I21lcm1haWQtMTczODE5MDY1MzYxMiAuYXJyb3doZWFkUGF0aHtmaWxsOiMzMzMzMzM7fSNtZXJtYWlkLTE3MzgxOTA2NTM2MTIgLmVkZ2VQYXRoIC5wYXRoe3N0cm9rZTojNjY2O3N0cm9rZS13aWR0aDoyLjBweDt9I21lcm1haWQtMTczODE5MDY1MzYxMiAuZmxvd2NoYXJ0LWxpbmt7c3Ryb2tlOiM2NjY7ZmlsbDpub25lO30jbWVybWFpZC0xNzM4MTkwNjUzNjEyIC5lZGdlTGFiZWx7YmFja2dyb3VuZC1jb2xvcjp3aGl0ZTt0ZXh0LWFsaWduOmNlbnRlcjt9I21lcm1haWQtMTczODE5MDY1MzYxMiAuZWRnZUxhYmVsIHJlY3R7b3BhY2l0eTowLjU7YmFja2dyb3VuZC1jb2xvcjp3aGl0ZTtmaWxsOndoaXRlO30jbWVybWFpZC0xNzM4MTkwNjUzNjEyIC5jbHVzdGVyIHJlY3R7ZmlsbDpoc2woMCwgMCUsIDk4LjkyMTU2ODYyNzUlKTtzdHJva2U6IzcwNzA3MDtzdHJva2Utd2lkdGg6MXB4O30jbWVybWFpZC0xNzM4MTkwNjUzNjEyIC5jbHVzdGVyIHRleHR7ZmlsbDojMzMzO30jbWVybWFpZC0xNzM4MTkwNjUzNjEyIC5jbHVzdGVyIHNwYW57Y29sb3I6IzMzMzt9I21lcm1haWQtMTczODE5MDY1MzYxMiBkaXYubWVybWFpZFRvb2x0aXB7cG9zaXRpb246YWJzb2x1dGU7dGV4dC1hbGlnbjpjZW50ZXI7bWF4LXdpZHRoOjIwMHB4O3BhZGRpbmc6MnB4O2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTJweDtiYWNrZ3JvdW5kOmhzbCgtMTYwLCAwJSwgOTMuMzMzMzMzMzMzMyUpO2JvcmRlcjoxcHggc29saWQgIzcwNzA3MDtib3JkZXItcmFkaXVzOjJweDtwb2ludGVyLWV2ZW50czpub25lO3otaW5kZXg6MTAwO30jbWVybWFpZC0xNzM4MTkwNjUzNjEyIDpyb290ey0tbWVybWFpZC1mb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7fTwvc3R5bGU+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxtYXJrZXIgaWQ9ImZsb3djaGFydC1wb2ludEVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iOSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDAgTCAxMCA1IEwgMCAxMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyI+PC9wYXRoPjwvbWFya2VyPjxtYXJrZXIgaWQ9ImZsb3djaGFydC1wb2ludFN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSIwIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgNSBMIDEwIDEwIEwgMTAgMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyI+PC9wYXRoPjwvbWFya2VyPjxtYXJrZXIgaWQ9ImZsb3djaGFydC1jaXJjbGVFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjExIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiPjwvY2lyY2xlPjwvbWFya2VyPjxtYXJrZXIgaWQ9ImZsb3djaGFydC1jaXJjbGVTdGFydCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iLTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyI+PC9jaXJjbGU+PC9tYXJrZXI+PG1hcmtlciBpZD0iZmxvd2NoYXJ0LWNyb3NzRW5kIiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSIxMiIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyI+PC9wYXRoPjwvbWFya2VyPjxtYXJrZXIgaWQ9ImZsb3djaGFydC1jcm9zc1N0YXJ0IiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSItMSIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyI+PC9wYXRoPjwvbWFya2VyPjxnIGNsYXNzPSJyb290Ij48ZyBjbGFzcz0iY2x1c3RlcnMiPjwvZz48ZyBjbGFzcz0iZWRnZVBhdGhzIj48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbHMiPjwvZz48ZyBjbGFzcz0ibm9kZXMiPjxnIGNsYXNzPSJyb290IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjUsIDApIj48ZyBjbGFzcz0iY2x1c3RlcnMiPjxnIGNsYXNzPSJjbHVzdGVyIGRlZmF1bHQiIGlkPSJ0b3AiPjxyZWN0IHN0eWxlPSJmaWxsOndoaXRlOyIgcng9IjAiIHJ5PSIwIiB4PSI4IiB5PSI4IiB3aWR0aD0iNTIwLjQ5MjE4NzUiIGhlaWdodD0iNzA1Ij48L3JlY3Q+PGcgY2xhc3M9ImNsdXN0ZXItbGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI2OC4yNDYwOTM3NSwgMTMpIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZVBhdGhzIj48cGF0aCBkPSJNMzEyLjY0ODQzNzUsNTcuMDAzMzM0OTU1NDg2MjJMMjkzLjg1Njc3MDgzMzMzMzMsNjIuNzUyNzc5MTI5NTcxODVDMjc1LjA2NTEwNDE2NjY2NjcsNjguNTAyMjIzMzAzNjU3NDksMjM3LjQ4MTc3MDgzMzMzMzM0LDgwLjAwMTExMTY1MTgyODc0LDIxOC42OTAxMDQxNjY2NjY2Niw4OS45MTcyMjI0OTI1ODEwNUMxOTkuODk4NDM3NSw5OS44MzMzMzMzMzMzMzMzMywxOTkuODk4NDM3NSwxMDguMTY2NjY2NjY2NjY2NjcsMTk5Ljg5ODQzNzUsMTEyLjMzMzMzMzMzMzMzMzMzTDE5OS44OTg0Mzc1LDExNi41IiBpZD0iTC1OZXctdHJpYWdlLTAiIGNsYXNzPSIgZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1OZXcgTEUtdHJpYWdlIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNmbG93Y2hhcnQtcG9pbnRFbmQpIj48L3BhdGg+PHBhdGggZD0iTTM4MC41NDU2MTEyMTMyMzUzLDIxOC41TDM4My4yNTAyNDg5Mjc2OTYxLDIxMi43OTE2NjY2NjY2NjY2NkMzODUuOTU0ODg2NjQyMTU2OSwyMDcuMDgzMzMzMzMzMzMzMzQsMzkxLjM2NDE2MjA3MTA3ODQ1LDE5NS42NjY2NjY2NjY2NjY2NiwzOTQuMDY4Nzk5Nzg1NTM5MTcsMTgxLjQ1ODMzMzMzMzMzMzM0QzM5Ni43NzM0Mzc1LDE2Ny4yNSwzOTYuNzczNDM3NSwxNTAuMjUsMzk2Ljc3MzQzNzUsMTM0Ljc5MTY2NjY2NjY2NjY2QzM5Ni43NzM0Mzc1LDExOS4zMzMzMzMzMzMzMzMzMywzOTYuNzczNDM3NSwxMDUuNDE2NjY2NjY2NjY2NjcsMzkwLjY1NDk0NzkxNjY2NjcsOTQuMjMwMzM3MTY5NDU3NTRDMzg0LjUzNjQ1ODMzMzMzMzMsODMuMDQ0MDA3NjcyMjQ4NDQsMzcyLjI5OTQ3OTE2NjY2NjcsNzQuNTg4MDE1MzQ0NDk2OSwzNjYuMTgwOTg5NTgzMzMzMyw3MC4zNjAwMTkxODA2MjExMUwzNjAuMDYyNSw2Ni4xMzIwMjMwMTY3NDUzNCIgaWQ9IkwtT3Blbi1OZXctMCIgY2xhc3M9IiBlZGdlLXRoaWNrbmVzcy1ub3JtYWwgZWRnZS1wYXR0ZXJuLXNvbGlkIGZsb3djaGFydC1saW5rIExTLU9wZW4gTEUtTmV3IiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNmbG93Y2hhcnQtcG9pbnRFbmQpIj48L3BhdGg+PHBhdGggZD0iTTE3MS42MTY3NzU4MTE4ODcyNywxNTBMMTYxLjk3ODQ5ODA3MjQwNjA0LDE1NS43MDgzMzMzMzMzMzMzNEMxNTIuMzQwMjIwMzMyOTI0ODQsMTYxLjQxNjY2NjY2NjY2NjY2LDEzMy4wNjM2NjQ4NTM5NjI0MiwxNzIuODMzMzMzMzMzMzMzMzQsMTMwLjIzNzA0Mjk5NDI4MTA0LDE4NC4yNUMxMjcuNDEwNDIxMTM0NTk5NjcsMTk1LjY2NjY2NjY2NjY2NjY2LDE0MS4wMzM3MzI4OTQxOTkzNSwyMDcuMDgzMzMzMzMzMzMzMzQsMTQ3Ljg0NTM4ODc3Mzk5OTE2LDIxMi43OTE2NjY2NjY2NjY2NkwxNTQuNjU3MDQ0NjUzNzk5LDIxOC41IiBpZD0iTC10cmlhZ2UtUmVzb2x2ZWRJbmNvbXBsZXRlLTAiIGNsYXNzPSIgZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy10cmlhZ2UgTEUtUmVzb2x2ZWRJbmNvbXBsZXRlIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNmbG93Y2hhcnQtcG9pbnRFbmQpIj48L3BhdGg+PHBhdGggZD0iTTE5NC42MzIwMTc4NDYyMDEsMjE4LjVMMjAxLjQ0MzY3MzcyNjAwMDg0LDIxMi43OTE2NjY2NjY2NjY2NkMyMDguMjU1MzI5NjA1ODAwNjUsMjA3LjA4MzMzMzMzMzMzMzM0LDIyMS44Nzg2NDEzNjU0MDAzNCwxOTUuNjY2NjY2NjY2NjY2NjYsMjI0LjcwNTI2MzIyNTA4MTcyLDE4NC4yNUMyMjcuNTMxODg1MDg0NzYzMDgsMTcyLjgzMzMzMzMzMzMzMzM0LDIxOS41NjE4MTcwNDQ1MjYxNSwxNjEuNDE2NjY2NjY2NjY2NjYsMjE1LjU3Njc4MzAyNDQwNzcyLDE1NS43MDgzMzMzMzMzMzMzNEwyMTEuNTkxNzQ5MDA0Mjg5MjMsMTUwIiBpZD0iTC1SZXNvbHZlZEluY29tcGxldGUtdHJpYWdlLTAiIGNsYXNzPSIgZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1SZXNvbHZlZEluY29tcGxldGUgTEUtdHJpYWdlIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNmbG93Y2hhcnQtcG9pbnRFbmQpIj48L3BhdGg+PHBhdGggZD0iTTE3NC42NDQ1MzEyNSwyNTJMMTc0LjY0NDUzMTI1LDI1Ny43MDgzMzMzMzMzMzMzQzE3NC42NDQ1MzEyNSwyNjMuNDE2NjY2NjY2NjY2NywxNzQuNjQ0NTMxMjUsMjc0LjgzMzMzMzMzMzMzMzMsMTc0LjY0NDUzMTI1LDI4Ni4yNUMxNzQuNjQ0NTMxMjUsMjk3LjY2NjY2NjY2NjY2NjcsMTc0LjY0NDUzMTI1LDMwOS4wODMzMzMzMzMzMzMzLDE3NC42NDQ1MzEyNSwzMTQuNzkxNjY2NjY2NjY2N0wxNzQuNjQ0NTMxMjUsMzIwLjUiIGlkPSJMLVJlc29sdmVkSW5jb21wbGV0ZS1DbG9zZWRJbmNvbXBsZXRlLTAiIGNsYXNzPSIgZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1SZXNvbHZlZEluY29tcGxldGUgTEUtQ2xvc2VkSW5jb21wbGV0ZSIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjZmxvd2NoYXJ0LXBvaW50RW5kKSI+PC9wYXRoPjxwYXRoIGQ9Ik0xNzQuNjQ0NTMxMjUsMzU0TDE3NC42NDQ1MzEyNSwzNTguMTY2NjY2NjY2NjY2N0MxNzQuNjQ0NTMxMjUsMzYyLjMzMzMzMzMzMzMzMzMsMTc0LjY0NDUzMTI1LDM3MC42NjY2NjY2NjY2NjY3LDE3NC42NDQ1MzEyNSwzODEuNzkxNjY2NjY2NjY2N0MxNzQuNjQ0NTMxMjUsMzkyLjkxNjY2NjY2NjY2NjcsMTc0LjY0NDUzMTI1LDQwNi44MzMzMzMzMzMzMzMzLDE3NC42NDQ1MzEyNSw0MjAuNzVDMTc0LjY0NDUzMTI1LDQzNC42NjY2NjY2NjY2NjY3LDE3NC42NDQ1MzEyNSw0NDguNTgzMzMzMzMzMzMzMywxNzQuNjQ0NTMxMjUsNDYyLjVDMTc0LjY0NDUzMTI1LDQ3Ni40MTY2NjY2NjY2NjY3LDE3NC42NDQ1MzEyNSw0OTAuMzMzMzMzMzMzMzMzMywxNzQuNjQ0NTMxMjUsNTA0LjI1QzE3NC42NDQ1MzEyNSw1MTguMTY2NjY2NjY2NjY2NiwxNzQuNjQ0NTMxMjUsNTMyLjA4MzMzMzMzMzMzMzQsMTc0LjY0NDUzMTI1LDU0NkMxNzQuNjQ0NTMxMjUsNTU5LjkxNjY2NjY2NjY2NjYsMTc0LjY0NDUzMTI1LDU3My44MzMzMzMzMzMzMzM0LDE3NC42NDQ1MzEyNSw1ODcuNzVDMTc0LjY0NDUzMTI1LDYwMS42NjY2NjY2NjY2NjY2LDE3NC42NDQ1MzEyNSw2MTUuNTgzMzMzMzMzMzMzNCwxODQuODY4ODE1MTA0MTY2NjYsNjI2Ljk4MzAxNDYyNDY5NkMxOTUuMDkzMDk4OTU4MzMzMzQsNjM4LjM4MjY5NTkxNjA1ODgsMjE1LjU0MTY2NjY2NjY2NjY2LDY0Ny4yNjUzOTE4MzIxMTc0LDIyNS43NjU5NTA1MjA4MzMzNCw2NTEuNzA2NzM5NzkwMTQ2OEwyMzUuOTkwMjM0Mzc1LDY1Ni4xNDgwODc3NDgxNzYyIiBpZD0iTC1DbG9zZWRJbmNvbXBsZXRlLUNsb3NlZC0wIiBjbGFzcz0iIGVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtQ2xvc2VkSW5jb21wbGV0ZSBMRS1DbG9zZWQiIHN0eWxlPSJmaWxsOm5vbmU7IiBtYXJrZXItZW5kPSJ1cmwoI2Zsb3djaGFydC1wb2ludEVuZCkiPjwvcGF0aD48cGF0aCBkPSJNMjI4LjI3NTAzNjM4MTc0MDIsMTUwTDIzNy45NDU2NjgzMzg5NTAxOCwxNTUuNzA4MzMzMzMzMzMzMzRDMjQ3LjYxNjMwMDI5NjE2MDEyLDE2MS40MTY2NjY2NjY2NjY2NiwyNjYuOTU3NTY0MjEwNTgwMSwxNzIuODMzMzMzMzMzMzMzMzQsMjg2LjU1NjI1NjA2MzYyMzQsMTg0LjQwODA1MzQ4NzUxMjU1QzMwNi4xNTQ5NDc5MTY2NjY3LDE5NS45ODI3NzM2NDE2OTE3NSwzMjYuMDExMDY3NzA4MzMzMywyMDcuNzE1NTQ3MjgzMzgzNDcsMzM1LjkzOTEyNzYwNDE2NjcsMjEzLjU4MTkzNDEwNDIyOTM2TDM0NS44NjcxODc1LDIxOS40NDgzMjA5MjUwNzUyNSIgaWQ9IkwtdHJpYWdlLU9wZW4tMCIgY2xhc3M9IiBlZGdlLXRoaWNrbmVzcy1ub3JtYWwgZWRnZS1wYXR0ZXJuLXNvbGlkIGZsb3djaGFydC1saW5rIExTLXRyaWFnZSBMRS1PcGVuIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNmbG93Y2hhcnQtcG9pbnRFbmQpIj48L3BhdGg+PHBhdGggZD0iTTM1NC40NjIyNTg3MzE2MTc2LDI1MkwzNDguMjc3NzkzNzM0NjgxNCwyNTcuNzA4MzMzMzMzMzMzM0MzNDIuMDkzMzI4NzM3NzQ1LDI2My40MTY2NjY2NjY2NjY3LDMyOS43MjQzOTg3NDM4NzI1NCwyNzQuODMzMzMzMzMzMzMzMywzMjMuNTM5OTMzNzQ2OTM2MjQsMjg5LjA0MTY2NjY2NjY2NjdDMzE3LjM1NTQ2ODc1LDMwMy4yNSwzMTcuMzU1NDY4NzUsMzIwLjI1LDMxNy4zNTU0Njg3NSwzMzUuNzA4MzMzMzMzMzMzM0MzMTcuMzU1NDY4NzUsMzUxLjE2NjY2NjY2NjY2NjcsMzE3LjM1NTQ2ODc1LDM2NS4wODMzMzMzMzMzMzMzLDMyMi44Njk4MzA2NTExOTc2LDM3Ni4yMDgzMzMzMzMzMzMzQzMyOC4zODQxOTI1NTIzOTUyMywzODcuMzMzMzMzMzMzMzMzMywzMzkuNDEyOTE2MzU0NzkwNCwzOTUuNjY2NjY2NjY2NjY2NywzNDQuOTI3Mjc4MjU1OTg4LDM5OS44MzMzMzMzMzMzMzMzTDM1MC40NDE2NDAxNTcxODU2NSw0MDQiIGlkPSJMLU9wZW4tc3RhdGVzLTAiIGNsYXNzPSIgZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1PcGVuIExFLXN0YXRlcyIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjZmxvd2NoYXJ0LXBvaW50RW5kKSI+PC9wYXRoPjxwYXRoIGQ9Ik0zODMuNjI1OTM4MjY1OTMxNCwyNTJMMzg3LjM4MDMzOTE3OTk0Mjg0LDI1Ny43MDgzMzMzMzMzMzMzQzM5MS4xMzQ3NDAwOTM5NTQyNCwyNjMuNDE2NjY2NjY2NjY2NywzOTguNjQzNTQxOTIxOTc3MTUsMjc0LjgzMzMzMzMzMzMzMzMsNDAyLjM5Nzk0MjgzNTk4ODU0LDI4Ni4yNUM0MDYuMTUyMzQzNzUsMjk3LjY2NjY2NjY2NjY2NjcsNDA2LjE1MjM0Mzc1LDMwOS4wODMzMzMzMzMzMzMzLDQwNi4xNTIzNDM3NSwzMTQuNzkxNjY2NjY2NjY2N0w0MDYuMTUyMzQzNzUsMzIwLjUiIGlkPSJMLU9wZW4tSW5Qcm9ncmVzcy0wIiBjbGFzcz0iIGVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtT3BlbiBMRS1JblByb2dyZXNzIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLXN0YXJ0PSJ1cmwoI2Zsb3djaGFydC1wb2ludFN0YXJ0KSIgbWFya2VyLWVuZD0idXJsKCNmbG93Y2hhcnQtcG9pbnRFbmQpIj48L3BhdGg+PHBhdGggZD0iTTQwNi4xNTIzNDM3NSwzNTRMNDA2LjE1MjM0Mzc1LDM1OC4xNjY2NjY2NjY2NjY3QzQwNi4xNTIzNDM3NSwzNjIuMzMzMzMzMzMzMzMzMyw0MDYuMTUyMzQzNzUsMzcwLjY2NjY2NjY2NjY2NjcsNDAyLjgwNDc0MjA3ODM0MzMsMzc5QzM5OS40NTcxNDA0MDY2ODY2LDM4Ny4zMzMzMzMzMzMzMzMzLDM5Mi43NjE5MzcwNjMzNzMyLDM5NS42NjY2NjY2NjY2NjY3LDM4OS40MTQzMzUzOTE3MTY2LDM5OS44MzMzMzMzMzMzMzMzTDM4Ni4wNjY3MzM3MjAwNTk4Niw0MDQiIGlkPSJMLUluUHJvZ3Jlc3Mtc3RhdGVzLTAiIGNsYXNzPSIgZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1JblByb2dyZXNzIExFLXN0YXRlcyIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjZmxvd2NoYXJ0LXBvaW50RW5kKSI+PC9wYXRoPjxwYXRoIGQ9Ik0zMzEuODAzOTc0MDgzMDgzODYsNDM3LjVMMzIxLjY1MzM3Njg0MDA2OTksNDQxLjY2NjY2NjY2NjY2NjdDMzExLjUwMjc3OTU5NzA1NTksNDQ1LjgzMzMzMzMzMzMzMzMsMjkxLjIwMTU4NTExMTAyNzk1LDQ1NC4xNjY2NjY2NjY2NjY3LDI4MS4wNTA5ODc4NjgwMTQsNDY1LjI5MTY2NjY2NjY2NjdDMjcwLjkwMDM5MDYyNSw0NzYuNDE2NjY2NjY2NjY2NywyNzAuOTAwMzkwNjI1LDQ5MC4zMzMzMzMzMzMzMzMzLDI3MC45MDAzOTA2MjUsNTA0LjI1QzI3MC45MDAzOTA2MjUsNTE4LjE2NjY2NjY2NjY2NjYsMjcwLjkwMDM5MDYyNSw1MzIuMDgzMzMzMzMzMzMzNCwyNzAuOTAwMzkwNjI1LDU0NkMyNzAuOTAwMzkwNjI1LDU1OS45MTY2NjY2NjY2NjY2LDI3MC45MDAzOTA2MjUsNTczLjgzMzMzMzMzMzMzMzQsMjcwLjkwMDM5MDYyNSw1ODcuNzVDMjcwLjkwMDM5MDYyNSw2MDEuNjY2NjY2NjY2NjY2NiwyNzAuOTAwMzkwNjI1LDYxNS41ODMzMzMzMzMzMzM0LDI3MC44ODU5NjYzNDg1NTI5LDYyNi43MDgzMzMzMzMzMzM0QzI3MC44NzE1NDIwNzIxMDU4LDYzNy44MzMzMzMzMzMzMzM0LDI3MC44NDI2OTM1MTkyMTE2LDY0Ni4xNjY2NjY2NjY2NjY2LDI3MC44MjgyNjkyNDI3NjQ1LDY1MC4zMzMzMzMzMzMzMzM0TDI3MC44MTM4NDQ5NjYzMTc0LDY1NC41IiBpZD0iTC1zdGF0ZXMtQ2xvc2VkLTAiIGNsYXNzPSIgZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1zdGF0ZXMgTEUtQ2xvc2VkIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNmbG93Y2hhcnQtcG9pbnRFbmQpIj48L3BhdGg+PHBhdGggZD0iTTM4OC4zMzA1MjI1NDg2NTI3LDQzNy41TDM5Mi4yNDEyNTU3Njk3MTA1Niw0NDEuNjY2NjY2NjY2NjY2N0MzOTYuMTUxOTg4OTkwNzY4NCw0NDUuODMzMzMzMzMzMzMzMyw0MDMuOTczNDU1NDMyODg0MjQsNDU0LjE2NjY2NjY2NjY2NjcsNDA3Ljg4NDE4ODY1Mzk0MjE1LDQ2Mi41QzQxMS43OTQ5MjE4NzUsNDcwLjgzMzMzMzMzMzMzMzMsNDExLjc5NDkyMTg3NSw0NzkuMTY2NjY2NjY2NjY2Nyw0MTEuNzk0OTIxODc1LDQ4My4zMzMzMzMzMzMzMzMzTDQxMS43OTQ5MjE4NzUsNDg3LjUiIGlkPSJMLXN0YXRlcy1SZXNvbHZlZC0wIiBjbGFzcz0iIGVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtc3RhdGVzIExFLVJlc29sdmVkIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNmbG93Y2hhcnQtcG9pbnRFbmQpIj48L3BhdGg+PHBhdGggZD0iTTQxMS43OTQ5MjE4NzUsNTIxTDQxMS43OTQ5MjE4NzUsNTI1LjE2NjY2NjY2NjY2NjZDNDExLjc5NDkyMTg3NSw1MjkuMzMzMzMzMzMzMzMzNCw0MTEuNzk0OTIxODc1LDUzNy42NjY2NjY2NjY2NjY2LDQxMS43OTQ5MjE4NzUsNTQ2QzQxMS43OTQ5MjE4NzUsNTU0LjMzMzMzMzMzMzMzMzQsNDExLjc5NDkyMTg3NSw1NjIuNjY2NjY2NjY2NjY2Niw0MTEuNzk0OTIxODc1LDU2Ni44MzMzMzMzMzMzMzM0TDQxMS43OTQ5MjE4NzUsNTcxIiBpZD0iTC1SZXNvbHZlZC1WZXJpZnktMCIgY2xhc3M9IiBlZGdlLXRoaWNrbmVzcy1ub3JtYWwgZWRnZS1wYXR0ZXJuLWRvdHRlZCBmbG93Y2hhcnQtbGluayBMUy1SZXNvbHZlZCBMRS1WZXJpZnkiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlLXdpZHRoOjJweDtzdHJva2UtZGFzaGFycmF5OjM7IiBtYXJrZXItZW5kPSJ1cmwoI2Zsb3djaGFydC1wb2ludEVuZCkiPjwvcGF0aD48cGF0aCBkPSJNNDExLjc5NDkyMTg3NSw2MDQuNUw0MTEuNzk0OTIxODc1LDYwOC42NjY2NjY2NjY2NjY2QzQxMS43OTQ5MjE4NzUsNjEyLjgzMzMzMzMzMzMzMzQsNDExLjc5NDkyMTg3NSw2MjEuMTY2NjY2NjY2NjY2NiwzOTQuMDgyNjgyMjkxNjY2Nyw2MzAuNTc2NDYyMzYwODI2NEMzNzYuMzcwNDQyNzA4MzMzMyw2MzkuOTg2MjU4MDU0OTg2MywzNDAuOTQ1OTYzNTQxNjY2Nyw2NTAuNDcyNTE2MTA5OTcyNSwzMjMuMjMzNzIzOTU4MzMzMyw2NTUuNzE1NjQ1MTM3NDY1N0wzMDUuNTIxNDg0Mzc1LDY2MC45NTg3NzQxNjQ5NTg4IiBpZD0iTC1WZXJpZnktQ2xvc2VkLTAiIGNsYXNzPSIgZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1WZXJpZnkgTEUtQ2xvc2VkIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNmbG93Y2hhcnQtcG9pbnRFbmQpIj48L3BhdGg+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWxzIj48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDM5Ni43NzM0Mzc1LCAxMzMuMjUpIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC04Ny41NTQ2ODc1LCAtOS4yNSkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIxNzUuMTA5Mzc1IiBoZWlnaHQ9IjE4LjUiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj5Nb3ZlIHRvIG5ldyBjb21wb25lbnQ8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTEzLjc4NzEwOTM3NSwgMTg0LjI1KSI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNzAuOTE3OTY4NzUsIC05LjI1KSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjE0MS44MzU5Mzc1IiBoZWlnaHQ9IjE4LjUiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj5zeW5jIHdpdGggc3VibWl0dGVyPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIzNS41MDE5NTMxMjUsIDE4NC4yNSkiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTMwLjc5Njg3NSwgLTkuMjUpIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iNjEuNTkzNzUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPkNsYXJpZmllZDwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNzQuNjQ0NTMxMjUsIDI4Ni4yNSkiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQ1Ljc3NzM0Mzc1LCAtOS4yNSkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSI5MS41NTQ2ODc1IiBoZWlnaHQ9IjE4LjUiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj5Ob3QgQ2xhcmlmaWVkPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIwIiBoZWlnaHQ9IjAiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjAiIGhlaWdodD0iMCI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIwIiBoZWlnaHQ9IjAiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjAiIGhlaWdodD0iMCI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIwIiBoZWlnaHQ9IjAiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjAiIGhlaWdodD0iMCI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZXMiPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCIgaWQ9ImZsb3djaGFydC1OZXctNDgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMzNi4zNTU0Njg3NSwgNDkuNzUpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iZmlsbDpsaWdodGdyZXk7IiByeD0iNSIgcnk9IjUiIHg9Ii0yMy43MDcwMzEyNSIgeT0iLTE2Ljc1IiB3aWR0aD0iNDcuNDE0MDYyNSIgaGVpZ2h0PSIzMy41Ij48L3JlY3Q+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTYuMjA3MDMxMjUsIC05LjI1KSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjMyLjQxNDA2MjUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPk5FVzwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGRlZmF1bHQiIGlkPSJmbG93Y2hhcnQtdHJpYWdlLTQ5IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxOTkuODk4NDM3NSwgMTMzLjI1KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9ImZpbGw6d2hpdGU7IiByeD0iMCIgcnk9IjAiIHg9Ii0yOC42NDQ1MzEyNSIgeT0iLTE2Ljc1IiB3aWR0aD0iNTcuMjg5MDYyNSIgaGVpZ2h0PSIzMy41Ij48L3JlY3Q+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMjEuMTQ0NTMxMjUsIC05LjI1KSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjQyLjI4OTA2MjUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPnRyaWFnZTwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGRlZmF1bHQiIGlkPSJmbG93Y2hhcnQtT3Blbi01MiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzcyLjYwOTM3NSwgMjM1LjI1KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9ImZpbGw6bGlnaHRncmV5OyIgcng9IjUiIHJ5PSI1IiB4PSItMjYuNzQyMTg3NSIgeT0iLTE2Ljc1IiB3aWR0aD0iNTMuNDg0Mzc1IiBoZWlnaHQ9IjMzLjUiPjwvcmVjdD48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xOS4yNDIxODc1LCAtOS4yNSkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIzOC40ODQzNzUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPk9QRU48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IiBpZD0iZmxvd2NoYXJ0LVJlc29sdmVkSW5jb21wbGV0ZS01MCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTc0LjY0NDUzMTI1LCAyMzUuMjUpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iZmlsbDpncmVlbjsiIHJ4PSI1IiByeT0iNSIgeD0iLTg1LjY1NjI1IiB5PSItMTYuNzUiIHdpZHRoPSIxNzEuMzEyNSIgaGVpZ2h0PSIzMy41Ij48L3JlY3Q+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNzguMTU2MjUsIC05LjI1KSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjE1Ni4zMTI1IiBoZWlnaHQ9IjE4LjUiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj48Zm9udCBjb2xvcj0id2hpdGUiPlJFU09MVkVEOkluY29tcGxldGU8L2ZvbnQ+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCIgaWQ9ImZsb3djaGFydC1DbG9zZWRJbmNvbXBsZXRlLTUxIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNzQuNjQ0NTMxMjUsIDMzNy4yNSkiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSJmaWxsOmxpZ2h0Z3JlZW47IiByeD0iNSIgcnk9IjUiIHg9Ii03Ny45MTAxNTYyNSIgeT0iLTE2Ljc1IiB3aWR0aD0iMTU1LjgyMDMxMjUiIGhlaWdodD0iMzMuNSI+PC9yZWN0PjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTcwLjQxMDE1NjI1LCAtOS4yNSkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIxNDAuODIwMzEyNSIgaGVpZ2h0PSIxOC41Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+PGZvbnQgY29sb3I9ImdyZWVuIj5DTE9TRUQ6SW5jb21wbGV0ZTwvZm9udD48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IiBpZD0iZmxvd2NoYXJ0LUNsb3NlZC01NyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjcwLjc1NTg1OTM3NSwgNjcxLjI1KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9ImZpbGw6bGlnaHRncmVlbjsiIHJ4PSI1IiByeT0iNSIgeD0iLTM0Ljc2NTYyNSIgeT0iLTE2Ljc1IiB3aWR0aD0iNjkuNTMxMjUiIGhlaWdodD0iMzMuNSI+PC9yZWN0PjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTI3LjI2NTYyNSwgLTkuMjUpIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iNTQuNTMxMjUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPjxmb250IGNvbG9yPSJncmVlbiI+Q0xPU0VEPC9mb250Pjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGRlZmF1bHQiIGlkPSJmbG93Y2hhcnQtc3RhdGVzLTU0IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzNzIuNjA5Mzc1LCA0MjAuNzUpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iZmlsbDp3aGl0ZTsiIHJ4PSIwIiByeT0iMCIgeD0iLTEyMC44ODI4MTI1IiB5PSItMTYuNzUiIHdpZHRoPSIyNDEuNzY1NjI1IiBoZWlnaHQ9IjMzLjUiPjwvcmVjdD48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xMTMuMzgyODEyNSwgLTkuMjUpIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMjI2Ljc2NTYyNSIgaGVpZ2h0PSIxOC41Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+Rml4ZWQsIFdvbid0IEZpeCwgRHVwbGljYXRlIGV0Yy48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IiBpZD0iZmxvd2NoYXJ0LUluUHJvZ3Jlc3MtNTMiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQwNi4xNTIzNDM3NSwgMzM3LjI1KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjUiIHJ5PSI1IiB4PSItNTMuNzk2ODc1IiB5PSItMTYuNzUiIHdpZHRoPSIxMDcuNTkzNzUiIGhlaWdodD0iMzMuNSI+PC9yZWN0PjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQ2LjI5Njg3NSwgLTkuMjUpIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iOTIuNTkzNzUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPjxmb250IGNvbG9yPSJibHVlIj5JTiBQUk9HUkVTUzwvZm9udD48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IiBpZD0iZmxvd2NoYXJ0LVJlc29sdmVkLTU1IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0MTEuNzk0OTIxODc1LCA1MDQuMjUpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iZmlsbDpncmVlbjsiIHJ4PSI1IiByeT0iNSIgeD0iLTQyLjUxMTcxODc1IiB5PSItMTYuNzUiIHdpZHRoPSI4NS4wMjM0Mzc1IiBoZWlnaHQ9IjMzLjUiPjwvcmVjdD48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0zNS4wMTE3MTg3NSwgLTkuMjUpIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iNzAuMDIzNDM3NSIgaGVpZ2h0PSIxOC41Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+PGZvbnQgY29sb3I9IndoaXRlIj5SRVNPTFZFRDwvZm9udD48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IiBpZD0iZmxvd2NoYXJ0LVZlcmlmeS01NiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNDExLjc5NDkyMTg3NSwgNTg3Ljc1KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9ImZpbGw6d2hpdGU7IiByeD0iMCIgcnk9IjAiIHg9Ii0yOC4zMzk4NDM3NSIgeT0iLTE2Ljc1IiB3aWR0aD0iNTYuNjc5Njg3NSIgaGVpZ2h0PSIzMy41Ij48L3JlY3Q+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMjAuODM5ODQzNzUsIC05LjI1KSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjQxLjY3OTY4NzUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPlZlcmlmeTwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48L2c+PC9nPjwvZz48L2c+PC9nPjwvc3ZnPg==" alt="" /> <p class="caption">JBS Issue Flow</p> </div> </div> <h2 id="triaging-an-issue">Triaging an issue</h2> <p>For most JDK areas, triage is performed on a regular basis (at least weekly) by triage teams. Each triage team consists of <a href="https://openjdk.org/bylaws#contributor">Contributors</a> who are area experts for a specific area or feature. If you haven’t been selected to be part of a triage team for a specific area <em>you shouldn’t be triaging bugs in that area</em>.</p> <p>When triaging an issue, first give it a general review.</p> <ol style="list-style-type: decimal"> <li>If the issue is a duplicate, close it as such.</li> <li>If the issue belongs to a different area (it was filed in libraries, but it’s an HotSpot issue), transfer it to the correct component/subcomponent making sure that the state remains <span class="jbs-value">New</span>.</li> <li>If the issue is incomplete, add a comment noting what is needed and resolve the bug as <span class="jbs-value">Resolved</span> - <span class="jbs-value">Incomplete</span>. This is the JBS way of saying “need more information”. If no more information is obtained within reasonable time, the issue should be closed (<span class="jbs-value">Closed</span> - <span class="jbs-value">Incomplete</span>).</li> </ol> <p>Now that the issue is in the right component and has the basic information, the analysis continues to get a more detailed understanding of the issue, and what should be done:</p> <ol style="list-style-type: decimal"> <li>Ensure the priority is correct. <ul> <li>An approach that has been used for getting a consistent view of priority is to consider three aspects of the issue: <strong>Impact</strong> of the issue; <strong>Likelihood</strong> of it occurring; and, whether there is a <strong>Workaround</strong>. The higher the impact and likelihood the higher the priority; then, having a workaround reduces that priority - but mostly where the impact and likelihood aren’t that severe.</li> </ul> </li> <li>Ensure the <span class="jbs-field">Affects Version/s</span> field is correct (within reason). <ul> <li>This may involve reproducing the bug, if doing so is fast and easy.</li> <li>In addition to the version where the bug was found, take special care to also investigate if the bug affects mainline. <ul> <li>See <a href="#indicating-what-releases-an-issue-is-applicable-to">Indicating what releases an issue is applicable to</a> for more details.</li> </ul> </li> <li>For enhancements the <span class="jbs-field">Affects Version/s</span> should be empty unless you feel that the enhancement is only relevant to a particular release family, and shouldn’t go into a future mainline release.</li> <li><span class="jbs-field">Affects Version/s</span> should never use any of the “special” values available in JBS like <span class="jbs-value">tbd</span>, <span class="jbs-value">na</span>, <span class="jbs-value">unknown</span>, <span class="jbs-value">(Rel)-pool</span> or similar. Only actual JDK release numbers should be used. If you want to reflect that an issue is relevant to an older release, use a family release value or an exact release if you know where the issue was introduced: <span class="jbs-value">8</span>, <span class="jbs-value">17</span>, <span class="jbs-value">21u4</span>.</li> </ul> </li> <li>Set the <span class="jbs-field">Fix Version/s</span>. <ul> <li>A bug should be fixed first in the most recent version where it exists. If you don’t know what version the fix will go into set the <span class="jbs-field">Fix Version/s</span> to <span class="jbs-value">tbd</span> or the appropriate <span class="jbs-value">(Rel)-pool</span> if the fix is for a specific release family. If there is a <span class="jbs-value">(Rel)-pool</span> in the fix version Skara tooling will use that issue/backport when you integrate the fix for that release family.</li> <li>If the bug also exists in older versions it may require <a href="#backporting">backporting</a>. <ul> <li>The decision to backport to a release should be made inline with the guidelines of the lead for that release.</li> <li>There are two options for creating backport issues to track the backport: one is to create it manually once it’s agreed that the bug should be backported; the second, is to let the bots create the backport issue once you integrate the fix to the repository (see <a href="#working-with-backports-in-jbs">Working with backports in JBS</a>). In most cases, letting the bots create the backport issue is preferred.</li> </ul> </li> <li>For Project internal changes intended to be integrated to a Project repository rather than the JDK or JDK Updates repositories, the <span class="jbs-field">Fix Version/s</span> should be set to <span class="jbs-value">internal</span>, or if the <a href="https://openjdk.org/bylaws#project">Project</a> is large enough to have its own <span class="jbs-value">repo-*</span> fix version, use that.</li> <li>Only one <span class="jbs-field">Fix Version/s</span> should ever be set. If the issue is to be fixed in additional releases then separate backport issues must be created (see <a href="#working-with-backports-in-jbs">Working with backports in JBS</a>). There are exceptions to this rule for CSRs and Release Notes.</li> </ul> </li> <li>Make sure the bug has all the required labels – see <a href="#jbs-label-dictionary">JBS Label Dictionary</a>. <ul> <li>Changes that don’t affect product code, but are only against the regression test, or problem-listing: <a href="#noreg-self"><span class="jbs-label">noreg-self</span></a></li> <li>Changes that don’t affect product code, but are only against documentation: <a href="#noreg-doc"><span class="jbs-label">noreg-doc</span></a></li> <li>Well contained issues that seem to be easy to fix: <a href="#starter"><span class="jbs-label">starter</span></a></li> <li>Enhancements that are pure cleanups: <a href="#cleanup"><span class="jbs-label">cleanup</span></a></li> <li>Project specific issues usually have their own labels as well</li> </ul> </li> <li>Managing regressions - for a bug (B) where behavior has <em>incorrectly</em> changed from a previous fix (A) ensure that the label <a href="#regression"><span class="jbs-label">regression</span></a> is added. Once it is known what fix caused the regression a <span class="jbs-value">caused by</span> link should be added to ‘B’ or a <span class="jbs-value">causes</span> link to ‘A’. A <span class="jbs-value">causes</span> link would also be added to A if the fix <em>causes</em> a change of behavior (intentional or otherwise) or it is found after integration, that additional work needs to be done. In addition to adding a <span class="jbs-value">caused by</span> link, set the <span class="jbs-field">Introduced in Version</span> and <span class="jbs-field">Introduced in Build</span> fields of ‘B’, based on which release ‘A’ was fixed in. Do not add a <span class="jbs-value">caused by</span> link if there was no specific product fix which <em>caused it</em>, for example, the addition of a test which finds an underlying problem should not be linked.</li> </ol> <p>At this point move the issue into the <span class="jbs-value">Open</span> state.</p> <h3 id="sensitive-information-e.g.-hs_err.log">Sensitive information (e.g. hs_err.log)</h3> <p>It may sound obvious, but avoid placing sensitive information in bug reports. Things like usernames, IP addresses, host names, and exact version information of third party libraries etc. may be crucial to be able to debug in some cases, but could also help an attacker gain information about your system. JBS is a public database that anyone can search, so be mindful of what you place there. In particular when attaching log files like the hs_err.log you should make sure that you are comfortable sharing the details exposed in it. Sometimes it may be better to leave a comment saying that these details can be obtained on request.</p> <p>If you file a bug through the <a href="https://bugreport.java.com/">Bug Report Tool</a> there’s a specific field that should be used to place sensitive information like this. Information placed there will not be part of the public bug report.</p> <h2 id="updating-an-issue-while-fixing">Updating an issue while fixing</h2> <p>Once you are made, or you make yourself, the assignee of an issue you take on the responsibility of moving the issue through to resolution - providing the current status, and ultimately leaving a record for others in the future to understand what happened. There are no set rules for how you manage the bug while you are assigned to it, as it depends on the type and importance of an issue. A simple update to the doc needs little to be done, fix the problem and close the issue; an intricate timing issue or crash should be handled differently - documenting your progress in identifying the problem (e.g. <a href="https://bugs.openjdk.org/browse/JDK-8212207">JDK-8212207</a>, <a href="https://bugs.openjdk.org/browse/JDK-6984895">JDK-6984895</a>, <a href="https://bugs.openjdk.org/browse/JDK-8287982">JDK-8287982</a>), this is especially helpful if you ultimately move the issue to a different area as you have found that the problem lies elsewhere, or is closed as <span class="jbs-value">Won’t Fix</span>. Your updates then provide a resource to others to better understand what has been done or the code itself. See <a href="https://stuartmarks.wordpress.com/2023/02/22/the-importance-of-writing-stuff-down"> The Importance of Writing Stuff Down</a> for a good explanation as to why it’s important.</p> <p>Some additional fields should be filled out or updated as you get a better understanding of the issue:</p> <ul> <li>The <span class="jbs-field">Description</span> usually explains what went wrong and how the failure was found, then there’s some investigation and eventually the root cause is found. At this point the <span class="jbs-field">Summary</span> should be updated to correctly describe the bug. The <span class="jbs-field">Description</span> however should remain a description of how the failure was found.</li> <li>The <span class="jbs-field">Affects Version/s</span> should be updated if you in your investigation finds that the issue is older than what is indicated by the current <span class="jbs-field">Affects Version/s</span>.</li> </ul> <h3 id="linking-issues">Linking Issues</h3> <p>An important aspect of any issue is making clear how it is connected/related to other issues. This can occur at any stage of the issue’s lifecycle. For example, as information becomes available that might suggest a cause, or similar issue (relates to).</p> <p>There are the following link types:</p> <p><span class="jbs-value">duplicate of</span> - Normally set automatically - see <a href="#closing-issues-as-duplicates">Closing issues as duplicates</a> for more information</p> <p><span class="jbs-value">backported by</span> - Normally set automatically when creating a backport with the “More -> Create Backport” option, or by the Skara tooling</p> <p><span class="jbs-value">CSR for</span> - When creating a CSR with the “More -> Create CSR” option, a link is automatically created between the main issue and the new CSR</p> <p><span class="jbs-value">blocks</span> - For when other issues are dependent on the current issue being resolved/fixed before they can be. For example, when a fix is broken down into a number of parts the <span class="jbs-value">blocks</span> link should be used to ensure they are all fixed before the main issue is considered resolved - see [implementing large changes](#implementing-large-changes]</p> <p><span class="jbs-value">relates to</span> - To avoid lots of <span class="jbs-value">relates to</span> links, the links should have some significance in relation to the cause and/or fix, for the current issue. In addition, relates links should not duplicate an existing <span class="jbs-value">duplicated by</span>, <span class="jbs-value">backported by</span>, <span class="jbs-value">csr for</span> or <span class="jbs-value">blocked by</span> link. In particular, it may be necessary to manually remove a <span class="jbs-value">relates to</span> link if it is later added as a <span class="jbs-value">duplicated by</span> or <span class="jbs-value">caused by</span> link</p> <p><span class="jbs-value">causes</span>/<span class="jbs-value">caused by</span> - the <span class="jbs-value">causes</span> link implies a stronger relationship than <span class="jbs-value">relates to</span>. If an issue ‘B’ can be traced back to the fix for issue ‘A’ then ‘A causes B’ (or ‘B is caused by A’)</p> <div class="note"> <p><strong>Note:</strong> If during your investigation of the bug you determine that the issue is in the wrong component, make sure to move it back to the <span class="jbs-value">New</span> state before moving it to the new component, so that it will be picked up by the component’s triage team. Make sure there is a comment outlining the reason for the move, as explained above.</p> </div> <h2 id="resolving-or-closing-an-issue">Resolving or Closing an issue</h2> <p>Once the work on an issue has been completed the issue’s <span class="jbs-field">Status</span> should be in a “completed” state. There are two “completed” states: <span class="jbs-value">Resolved</span> and <span class="jbs-value">Closed</span>. These are accompanied by a <span class="jbs-field">Resolution</span> and a <span class="jbs-value">Fix Version/s</span>. Which combination of <span class="jbs-field">Status</span>, <span class="jbs-field">Resolution</span>, and <span class="jbs-value">Fix Version/s</span> you should use depends on how the issue is completed.</p> <p>Most resolutions are used to close an issue so that it ends up being <span class="jbs-value">Closed</span> directly, but resolutions that indicates that a change has been integrated into a Project repository must go through the <span class="jbs-value">Resolved</span> state. An issue in <span class="jbs-value">Resolved</span> state needs to go through <a href="#verifying-an-issue">verification</a> to end up as <span class="jbs-value">Closed</span>. For the JDK Project in almost all cases the bots will transition the issue to <span class="jbs-value">Resolved</span>/<span class="jbs-value">Fixed</span> when the changeset is integrated to the repository.</p> <p>The <span class="jbs-field">Fix Version/s</span> field should indicate when an issue was fixed. The most common value for this field is a JDK version number. There are some special values available for this field in JBS, these should only be used for special cases as outlined in this Guide.</p> <div class="note"> <p><strong>Note:</strong> An issue should never be closed if it has open sub-tasks.</p> </div> <table> <colgroup> <col width="14%" /> <col width="85%" /></colgroup> <thead> <tr class="header"> <th align="left">Status<br /> Resolution</th> <th align="left">Covers</th> </tr> </thead> <tbody> <tr class="odd"> <td align="left"><span class="jbs-value">Resolved</span>/<span class="jbs-value">Closed</span><br /> <span class="jbs-value">Fixed</span></td> <td align="left">The resolution <span class="jbs-value">Fixed</span> should be used <strong>only</strong> if a change has been integrated in a Project repository to address the issue, and the <span class="jbs-field">Fix Version/s</span> must always correspond to the version where the change was integrated, or be one of the <span class="jbs-value">repo-*</span> fix versions or <span class="jbs-value">internal</span>. If there isn’t a fix in the repository (and so no associated changeset) then the issue should <strong>not</strong> be marked as <span class="jbs-field">Fixed</span>.</td> </tr> <tr class="even"> <td align="left"><span class="jbs-value">Closed</span><br /> <span class="jbs-value">Won’t Fix</span></td> <td align="left">Used when the issue is describing behavior which, while maybe problematic or not ideal, isn’t going to be changed - for compatibility reasons for example.</td> </tr> <tr class="odd"> <td align="left"><span class="jbs-value">Closed</span><br /> <span class="jbs-value">Duplicate</span></td> <td align="left">Used to indicate that the same issue is described in another JBS issue. See <a href="#closing-issues-as-duplicates">Closing issues as duplicates</a> for more information.</td> </tr> <tr class="even"> <td align="left"><span class="jbs-value">Resolved</span>/<span class="jbs-value">Closed</span><br /> <span class="jbs-value">Incomplete</span></td> <td align="left">Used to indicate that the JBS issue doesn’t contain enough information to work on the issue. See <a href="#closing-incomplete-issues">Closing incomplete issues</a> for more information.</td> </tr> <tr class="odd"> <td align="left"><span class="jbs-value">Closed</span><br /> <span class="jbs-value">Cannot Reproduce</span></td> <td align="left">Use when a reproducer is provided (or clear steps) but it’s not possible to see the faulty behavior. When you can’t reproduce an issue, where feasible try on the release the issue was reported against as a way of confirming that it’s indeed addressed on the latest release, rather than you not having the right environment in which to reproduce the issue.</td> </tr> <tr class="even"> <td align="left"><span class="jbs-value">Closed</span><br /> <span class="jbs-value">Other</span></td> <td align="left">Used in rare cases where none of the other statuses fit the situation.</td> </tr> <tr class="odd"> <td align="left"><span class="jbs-value">Closed</span><br /> <span class="jbs-value">External</span></td> <td align="left">Use where the issue is due to a problem in a Java library (not part of the OpenJDK code base), an IDE or other external tool etc. Where known, it’s good to provide a link to the site where the issue should be reported.</td> </tr> <tr class="even"> <td align="left"><span class="jbs-value">Closed</span><br /> <span class="jbs-value">Not an Issue</span></td> <td align="left">Use when the behavior is expected and valid (cf. <span class="jbs-value">Won’t Fix</span>) and the reporter perhaps has misunderstood what the behavior should be.</td> </tr> <tr class="odd"> <td align="left"><span class="jbs-value">Closed</span><br /> <span class="jbs-value">Migrated</span></td> <td align="left">Used rarely, but can be seen when issues are transferred into another project by opening up a separate issue in that project, with the issue in the original project being <span class="jbs-value">Closed</span>.</td> </tr> <tr class="even"> <td align="left"><span class="jbs-value">Resolved</span>/<span class="jbs-value">Closed</span><br /> <span class="jbs-value">Delivered</span></td> <td align="left">Used to close out issues where a change to the code isn’t required, common examples are Tasks, Release Notes, and umbrella issues for larger changes. Note that the verification step is always needed to move an issue from <span class="jbs-value">Resolved</span> to <span class="jbs-value">Closed</span>. If your issue doesn’t need verification (e.g. it’s an umbrella where each sub-task is verified as a separate fix) then please move the issue directly to <span class="jbs-value">Closed</span> without going through <span class="jbs-value">Resolved</span>.</td> </tr> <tr class="odd"> <td align="left"><span class="jbs-value">Closed</span><br /> <span class="jbs-value">Withdrawn</span></td> <td align="left"><span class="jbs-value">Withdrawn</span> is essentially the partner state to <span class="jbs-value">Delivered</span> for issues that would not have resulted in a fix to the repo, and also part of the <a href="https://wiki.openjdk.org/display/csr/Main">CSR</a> and <a href="#release-notes">Release Note</a> process.</td> </tr> <tr class="even"> <td align="left"><span class="jbs-value">Closed</span><br /> <span class="jbs-value">Approved</span></td> <td align="left">Used as part of the <a href="https://wiki.openjdk.org/display/csr/Main">CSR process</a>.</td> </tr> <tr class="odd"> <td align="left">Challenge States</td> <td align="left"><span class="jbs-value">Exclude [Challenge]</span>, <span class="jbs-value">Alternative Tests [Challenge]</span>, and <span class="jbs-value">Reject [Challenge]</span> are only relevant within the context of the JCK Project.</td> </tr> <tr class="even"> <td align="left"><span class="jbs-value">Future Project</span></td> <td align="left">This status is not recommended for use.</td> </tr> <tr class="odd"> <td align="left"><span class="jbs-value">Rejected</span></td> <td align="left">This status should not be used.</td> </tr> </tbody> </table> <div class="note"> <p>When an issue is closed as <span class="jbs-value">Won’t Fix</span>, do not remove the <span class="jbs-field">Fix Version/s</span>. It’s valuable information to know what version it was decided not to fix an issue in. The same goes for resolutions such as <span class="jbs-value">Duplicate</span>, <span class="jbs-value">Cannot Reproduce</span> and <span class="jbs-value">Not an Issue</span>.</p> </div> <div class="note"> <p>The fix version <span class="jbs-value">na</span> should only be used on backport issues that is created by mistake. See <a href="#how-to-fix-an-incorrect-backport-creation-in-jbs">How to fix an incorrect backport creation in JBS</a>.</p> </div> <h3 id="closing-issues-as-duplicates">Closing issues as duplicates</h3> <p>If the same issue is described in another JBS issue then close one against the other as <span class="jbs-value">Closed</span>/<span class="jbs-value">Duplicate</span>. In general the newer issue is closed as a <span class="jbs-value">Duplicate</span> of the older one, but where the newer issue has a clearer description, or more useful, up-to-date comments then doing it the other way round is ok as long as none of them has been <span class="jbs-value">Fixed</span> already. If one of the issues has been <span class="jbs-value">Fixed</span> the other one should be closed as a <span class="jbs-value">Duplicate</span> of the <span class="jbs-value">Fixed</span> issue. There may be other reasons to choose to close one or the other issue as the <span class="jbs-value">Duplicate</span>. As always - use your best judgement to make the end result as good as possible.</p> <div class="note"> <p>Any issue closed as a <span class="jbs-value">Duplicate</span> <strong>must</strong> have a “Duplicates” link to the duplicating issue.</p> </div> <div class="note"> <p>Be mindful of labels on issues closed as <span class="jbs-value">Duplicate</span>. Some labels need to be copied over to the duplicating issue, see for instance the <a href="#tck-red-rel"><span class="jbs-label">tck-red-</span><em>(Rel)</em></a> label.</p> </div> <h3 id="closing-issues-without-knowing-what-fixed-it">Closing issues without knowing what fixed it</h3> <p>If it’s determined that an issue has been fixed, but it’s unknown what change that fixed it, closing as <span class="jbs-value">Fixed</span> is not an option as this requires a changeset in a project repository. <span class="jbs-value">Duplicate</span> is also not an option since this requires a duplicate-link to the issue that fixed it. A common way to handle such cases is to close the issue as <span class="jbs-value">Delivered</span> with the <span class="jbs-value">Fix version/s</span> set to <span class="jbs-value">unknown</span>. Closing an issue as <span class="jbs-value">Cannot Reproduce</span> has also been common practice but is no longer recommended if it’s known that the issue has actually been fixed.</p> <h3 id="closing-incomplete-issues">Closing incomplete issues</h3> <p>As mentioned above, issues that lack the information needed to investigate the problem are placed in status <span class="jbs-value">Resolved</span> - <span class="jbs-value">Incomplete</span>. Triage teams should monitor incomplete issues in their area and if needed ping the relevant person. If the required information hasn’t been obtained within reasonable time (3-4 weeks) the bug should be closed as <span class="jbs-value">Incomplete</span>.</p> <h2 id="verifying-an-issue">Verifying an issue</h2> <p>Once an issue is marked as resolved there is now the option of someone, other than the person that fixed it, of marking it as <span class="jbs-value">Verified</span> to confirm that the issue is fixed after testing; marking it as <span class="jbs-value">Fix Failed</span> if it didn’t solve the issue; or, <span class="jbs-value">Not Verified</span> to indicate that it wasn’t explicitly tested. Note that the JBS UI doesn’t highlight when <span class="jbs-value">Fix Failed</span> has been set, you need to look for the <span class="jbs-field">Verification</span> field at the bottom of the left-hand column in the Details section.</p> <h2 id="removing-an-issue">Removing an issue</h2> <p>Removing a JBS issue is a rare extreme case that shouldn’t be part of the normal workflow. For this reason, removing issues is restricted to admins only. If you for some reason need to remove an issue, send an email to <a href="mailto:ops@openjdk.org">ops@openjdk.org</a>. You need to provide the bug id and a well considered reason the issue should be removed.</p> <p>Note that JBS issues are not removed just because something was a bad idea, or a reported issue turned out to be an embarrassing user mistake. Such issues are simply closed.</p> <h2 id="jbs-labels">JBS labels</h2> <p>JBS labels are used to tag and group related issues. JBS labels are an open namespace, which means that anyone can create new labels at any time. In order to avoid confusion, however, it’s best to reuse existing labels where possible. Most areas have their commonly used labels to identify issues in their respective area. Make an effort to find and use these labels. This can be done by editing the <span class="jbs-field">Labels</span> field of a bug and entering the first few characters of the label you want to add. JIRA will pop up an autocomplete window with existing labels that match that prefix. Then choose one of the existing labels. Using the autocomplete window is preferable to typing the whole label name (even if you’re a good typist) because it’s easy for minor spelling errors to creep in, which can inadvertently introduce multiple labels with spurious spelling variations.</p> <p>JBS labels should not be used to write documentation - don’t try to write sentences using labels. Adding a number of random labels is unlikely to be helpful to anyone.</p> <div class="note"> <p><strong>Labels are case sensitive</strong> When using labels in Jira gadgets (like pie charts, heat maps, and statistics tables) Jira will be case-sensitive and treat e.g. OpenJDK and openjdk as two different labels. Searching however is case-insensitive. This means that if you group a set of issues in a gadget based on a label, and then click one of the groups to see the list of issues, that list will contain more results than the gadget if there are usages of the label with different casing. This can be very confusing and for this reason the recommendation is to stick with the commonly used case for all labels, regardless of your personal taste for upper or lower case letters. Most labels are lower case only, but there are examples where upper case letters are used in the most common version of a label. Use of the autocomplete popup window (described above) when adding labels will avoid inadvertent introduction of labels with differing case.</p> </div> <h2 id="jbs-label-dictionary">JBS label dictionary</h2> <p>This table contains some frequently used JBS labels and their meaning. Please help keeping this dictionary up to date by adding your favorite labels. This table doesn’t dictate how to use labels, but rather document how they are used. That said, obviously it will help everyone if we try to follow a common standard and use similar labels in the same way across all entities that use JBS.</p> <table class="dictionary" summary="JBS Label Dictionary"> <tr style="text-align:left;"> <th>Label</th> <th>Description</th> </tr> <tr> <td class="dictionary"><span id="area-interest"><em>(Area)</em><span class="jbs-label">-interest</span></span></td> <td class="dictionary">Used to indicate that an area (usually a team or <a href="https://openjdk.org/bylaws#project">Project</a>) is interested in the issue. This label doesn’t indicate ownership of the issue. E.g., <span class="jbs-label">redhat-interest</span>, <span class="jbs-label">azul-interest</span>, <span class="jbs-label">coin-interest</span></td> </tr> <tr> <td class="dictionary"><span id="area-related"><em>(Area)</em><span class="jbs-label">-related</span></span></td> <td class="dictionary">Used to indicate that an issue is related to a specific area (usually a feature or <a href="https://openjdk.org/bylaws#project">Project</a>). This label doesn’t indicate ownership of the issue. E.g., <span class="jbs-label">graal-related</span>, <span class="jbs-label">testcolo-related</span>, <span class="jbs-label">doc-related</span></td> </tr> <tr> <td class="dictionary"><span id="rel-bp"><em>(Rel)</em><span class="jbs-label">-bp</span></span></td> <td class="dictionary">Used to indicate that a bug would be suitable for backport to a release <em>(Rel)</em>. This isn’t a decision to backport, just a suggestion / recommendation. E.g., <span class="jbs-label">11-bp</span></td> </tr> <tr> <td class="dictionary"><span id="rel-critical-request"><em>(Rel)</em><span class="jbs-label">-critical-request</span></span><br /> <span id="rel-critical-approved"><em>(Rel)</em><span class="jbs-label">-critical-approved</span></span><br /> <span id="rel-critical-watch"><em>(Rel)</em><span class="jbs-label">-critical-watch</span></span></td> <td class="dictionary"> <p>Used in the ramp down phases of specific releases to request approval of changes that requires Project lead approval (or similar) to be included. <em>(Rel)</em> is the release in question. E.g., <span class="jbs-label">jdk11-critical-request</span></p> <p><em>(Rel)</em><span class="jbs-label">-critical-approved</span> is used to signal that the change has been approved for inclusion. E.g., <span class="jbs-label">jdk11-critical-approved</span><br /> <em>(Rel)</em><span class="jbs-label">-critical-watch</span> is used for issues that must get into a specific release but risk running late. The label is used while the issue is still in progress and is replaced with <em>(Rel)</em><span class="jbs-label">-critical-request</span> once the issue is resolved. E.g., <span class="jbs-label">jdk11-critical-watch</span></p> These labels are always placed on the main JBS issue, never on backports or subtasks.</td> </tr> <tr> <td class="dictionary"><span id="rel-defer-request"><em>(Rel)</em><span class="jbs-label">-defer-request</span></span><br /> <span id="rel-defer-yes"><em>(Rel)</em><span class="jbs-label">-defer-yes</span></span><br /> <span id="rel-defer-no"><em>(Rel)</em><span class="jbs-label">-defer-no</span></span></td> <td class="dictionary"> <p>Used to request deferral of changes that requires Project lead approval (or similar) to defer. <em>(Rel)</em> is the release in question. E.g., <span class="jbs-label">jdk12-defer-request</span></p> <p><em>(Rel)</em><span class="jbs-label">-defer-yes</span> and <em>(Rel)</em><span class="jbs-label">-defer-no</span> are used to indicate wether the deferral has been approved or not. E.g., <span class="jbs-label">jdk12-defer-yes</span></p> These labels are always placed on the main JBS issue, never on backports or subtasks. Further details are found in the <a href="https://openjdk.org/jeps/3#Bug-Deferral-Process">JDK Release Process</a>.</td> </tr> <tr> <td class="dictionary"><span id="rel-enhancement-request"><em>(Rel)</em><span class="jbs-label">-enhancement-request</span></span><br /> <span id="rel-enhancement-yes"><em>(Rel)</em><span class="jbs-label">-enhancement-yes</span></span><br /> <span id="rel-enhancement-no"><em>(Rel)</em><span class="jbs-label">-enhancement-no</span></span></td> <td class="dictionary"> <p>Used in the ramp down phases to request the late inclusion of an enhancement. <em>(Rel)</em> is the release in question. E.g., <span class="jbs-label">jdk10-enhancement-request</span></p> <p><em>(Rel)</em><span class="jbs-label">-enhancement-yes</span> and <em>(Rel)</em><span class="jbs-label">-enhancement-no</span> are used to indicate the response on the request. E.g., <span class="jbs-label">jdk10-enhancement-yes</span>, <span class="jbs-label">jdk10-enhancement-no</span></p> These labels are always placed on the main JBS issue, never on backports or subtasks. Further details are found in the <a href="https://openjdk.org/jeps/3#Late-Enhancement-Request-Process">JDK Release Process</a>.</td> </tr> <tr> <td class="dictionary"><span id="rel-fix-request"><em>(Rel)</em><span class="jbs-label">-fix-request</span></span><br /> <span id="rel-fix-SQE-ok"><em>(Rel)</em><span class="jbs-label">-fix-SQE-ok</span></span><br /> <span id="rel-fix-yes"><em>(Rel)</em><span class="jbs-label">-fix-yes</span></span><br /> <span id="rel-fix-no"><em>(Rel)</em><span class="jbs-label">-fix-no</span></span></td> <td class="dictionary"> <p>Used in ramp down phase 2 to indicate that an issue would be of interest to get integrated into release <em>(Rel)</em>. E.g., <span class="jbs-label">jdk12u-fix-request</span></p> <p><em>(Rel)</em><span class="jbs-label">-fix-SQE-ok</span> is used to indicate that the issue will be covered by the test plan for <em>(Rel)</em>. E.g., <span class="jbs-label">jdk12u-fix-SQE-ok</span><br /> <em>(Rel)</em><span class="jbs-label">-fix-yes</span> and <em>(Rel)</em><span class="jbs-label">-fix-no</span> are used to indicate wether an issue has been approved for backport to <em>(Rel)</em>. E.g., <span class="jbs-label">jdk12u-fix-yes</span></p> These labels are always placed on the main JBS issue, never on backports or subtasks. Further details are found in the <a href="https://openjdk.org/jeps/3#Fix-Request-Process">JDK Release Process</a>.</td> </tr> <tr> <td class="dictionary"><span id="rel-na"><em>(Rel)</em><span class="jbs-label">-na</span></span></td> <td class="dictionary"> <p>Labels of the form <span class="jbs-label">11-na</span> or <span class="jbs-label">21-na</span> should be used when a bug is not applicable to a <strong>more recent</strong> release family. See <a href="#usage-of-the-rel-na-label">Usage of the (Rel)-na Label</a>.</p> (Rel) can also refer to more general release atrifacts like <span class="jbs-label">oraclejdk-na</span>, <span class="jbs-label">openjdk-na</span>, and <span class="jbs-label">sap-aix-na</span> to indicate that the issue doesn’t affect code included in that specific atrifact.</td> </tr> <tr> <td class="dictionary"><span id="rel-wnf"><em>(Rel)</em><span class="jbs-label">-wnf</span></span></td> <td class="dictionary"> <p>Labels of the form <span class="jbs-label">11-wnf</span> or <span class="jbs-label">21-wnf</span> should be used to indicate that a bug is not going to be fixed in a release where it’s present. Note that there should only be <strong>one</strong> <em>(Rel)</em><span class="jbs-label">-wnf</span> label on any JBS issue. It is implied that earlier versions will not be fixed either.</p> Also see <a href="#usage-of-the-rel-wnf-label">Usage of the (Rel)-wnf Label</a>.</td> </tr> <tr> <td class="dictionary"><span id="team-triage-rel"><em>(Team)</em><span class="jbs-label">-triage-</span><em>(Rel)</em></span></td> <td class="dictionary"> <p>Used to indicate that <em>(Team)</em> has triaged this issue for release <em>(Rel)</em>. It’s encouraged that all open bugs are triaged on a regular basis so that old bugs aren’t forgotten. It’s therefore common to see several triage labels on the same issue which helps keeping track of which bugs have been triaged for each release. E.g., <span class="jbs-label">oracle-triage-13</span></p> There are many label variants that include the word triage in some form. The form described above is the only one recommended. Please refrain from using other forms.</td> </tr> <tr> <td class="dictionary"><span id="aot"><span class="jbs-label">aot</span></span></td> <td class="dictionary">Used to identify issues in the JVM feature Ahead of Time Compilation.</td> </tr> <tr> <td class="dictionary"><span id="appcds"><span class="jbs-label"><del>appcds</del></span></span></td> <td class="dictionary"><strong>Deprecated.</strong> Was used to identify issues in Application Class-Data Sharing. The <span class="jbs-label">cds</span> label is now used instead.</td> </tr> <tr> <td class="dictionary"><span id="c1"><span class="jbs-label">c1</span></span></td> <td class="dictionary">Used to identify issues in the JVM JIT compiler C1.</td> </tr> <tr> <td class="dictionary"><span id="c2"><span class="jbs-label">c2</span></span><br /> <span class="jbs-label">c2-</span><code>.*</code></td> <td class="dictionary"> <p>Used to identify issues in the JVM JIT compiler C2.</p> <span class="jbs-label">c2-</span><code>.*</code> labels are used to identify different C2 features. E.g., <span class="jbs-label">c2-intrinsic</span>, <span class="jbs-label">c2-loopopts</span></td> </tr> <tr> <td class="dictionary"><span id="cds"><span class="jbs-label">cds</span></span></td> <td class="dictionary">Used to identify issues in the JVM feature Class Data Sharing.</td> </tr> <tr> <td class="dictionary"><span id="cleanup"><span class="jbs-label">cleanup</span></span></td> <td class="dictionary">The <span class="jbs-label">cleanup</span> label is used to indicate enhancements which has no semantic changes, whose only purpose is to make the code more maintainable or better looking.</td> </tr> <tr> <td class="dictionary"><span id="compilercontrol"><span class="jbs-label">compilercontrol</span></span></td> <td class="dictionary">Used to identify issues in the JVM Compiler Control feature.</td> </tr> <tr> <td class="dictionary"><span id="conformance"><span class="jbs-label">conformance</span></span></td> <td class="dictionary">Used to identify all TCK related conformance issues.</td> </tr> <tr> <td class="dictionary"><span id="docker"><span class="jbs-label">docker</span></span></td> <td class="dictionary">Used to identify issues in docker support.</td> </tr> <tr> <td class="dictionary"><span id="footprint"><span class="jbs-label">footprint</span></span></td> <td class="dictionary">Used to identify issues affecting Java SE footprint. Issues with this label should also have a <span class="jbs-label">performance</span> label.</td> </tr> <tr> <td class="dictionary"><span id="gc"><span class="jbs-label">gc-</span><code>.*</code></span></td> <td class="dictionary"> <p>Used to identify issues in specific garbage collectors in the JVM. E.g., <span class="jbs-label">gc-g1</span>, <span class="jbs-label">gc-shenandoah</span>, <span class="jbs-label">gc-serial</span>, <span class="jbs-label">gc-epsilon</span></p> <p>There are also labels in use to identify different GC features or areas rather than GC algorithms. E.g., <span class="jbs-label">gc-g1-fullgc</span>, <span class="jbs-label">gc-largeheap</span>, <span class="jbs-label">gc-performance</span></p> Note that ZGC breaks this pattern and use the label <span class="jbs-label">zgc</span>.</td> </tr> <tr> <td class="dictionary"><span id="graal"><span class="jbs-label">graal</span></span></td> <td class="dictionary">Used to indicate that this is a Graal issue. (Something that needs to be fixed in Graal rather than in the JDK.)</td> </tr> <tr> <td class="dictionary"><span id="graal-integration"><span class="jbs-label">graal-integration</span></span></td> <td class="dictionary">Reserved for Graal integration umbrella bugs. The automated integration script will break if this label is used for other bugs.</td> </tr> <tr> <td class="dictionary"><span id="hgupdate-sync"><span class="jbs-label">hgupdate-sync</span></span></td> <td class="dictionary">Used to identify backport issues created as part of automatic syncing between releases.</td> </tr> <tr> <td class="dictionary"><span id="hs-nightly"><span class="jbs-label"><del>hs-nightly</del></span></span></td> <td class="dictionary"><strong>Deprecated.</strong> Was used to tag bugs found in the HotSpot nightly testing. Since we are now running tiered testing there is no more nightly HotSpot testing. See <span class="jbs-label">tier</span><code>[1-8]</code>.</td> </tr> <tr> <td class="dictionary"><span id="hs-sbr"><span class="jbs-label">hs-sbr</span></span></td> <td class="dictionary">Used to identify issues that are found in the “same binary runs”, a stress testing method used to find intermittent failures.</td> </tr> <tr> <td class="dictionary"><span id="hs-tier"><del><span class="jbs-label">hs-tier</span><code>[1-8]</code></del></span></td> <td class="dictionary"><strong>Deprecated.</strong> Was used to identify which HotSpot tier a test failure was seen in. We don’t separate HotSpot tiers from the JDK tiers anymore. See <span class="jbs-label">tier</span><code>[1-8]</code>.</td> </tr> <tr> <td class="dictionary"><span id="i18n"><span class="jbs-label">i18n</span></span></td> <td class="dictionary">Used to identify issues in internationalization. i18n is short for internationalization meaning “i 18 letters and an n”. Used for bugs whose impact varies depending on a user’s writing system, language, or locale, but aren’t just a matter of locale data. The label isn’t needed for classes_text, classes_util_i18n, classes_awt_im, classes_fontprop, or char_encodings.</td> </tr> <tr> <td class="dictionary"><span id="integration-blocker"><span class="jbs-label">integration-blocker</span></span></td> <td class="dictionary">Used to indicate that a bug is present in a downstream repository but not present in the upstream repository and is therefore blocking integration of downstream changes into upstream.</td> </tr> <tr> <td class="dictionary"><span id="intermittent"><span class="jbs-label">intermittent</span></span><br /> <span id="intermittent-environment"><span class="jbs-label">intermittent-environment</span></span><br /> <span id="intermittent-hardware"><span class="jbs-label">intermittent-hardware</span></span></td> <td class="dictionary"> <p>An intermittent issue is one that fails sometimes but not always. The exact reason for the intermittent failure is per definition unknown. Once the reason has been identified the issue is no more considered intermittent. An issue isn’t intermittent if some characteristics has been found that triggers the failure consistently, even if the actual cause for the failure hasn’t been found. For instance if a test fails every time it’s executed on a specific host but not on other hosts it wouldn’t be considered intermittent as it fails consistently on that specific host. In other cases it may be that we know that a test sometimes is unlucky in some respect and fails due to this. This test could still be considered intermittent even though we know what the reason is if the reason itself appears intermittently.</p> <p>Some issues may seem intermittent when looking at test results, even though the reason for failing is actually known. One example is where a test fails consistently on a specific host, or due to specific conditions in the environment. These failures shouldn’t be considered intermittent but it may still be valuable to tag these in JBS with one of the labels <span class="jbs-label">intermittent-hardware</span> or <span class="jbs-label">intermittent-environment</span>. This will help to faster identify that the cause of the failure is known without having to read through the entire bug.</p> A test that should be platform agnostic but is consistently failing on a specific OS would for instance be labeled with <span class="jbs-label">intermittent-environment</span>, while a test that fails every time it’s run on some specific hardware would be labeled with <span class="jbs-label">intermittent-hardware</span>.</td> </tr> <tr> <td class="dictionary"><span id="jep-superseded"><span class="jbs-label">jep-superseded</span></span></td> <td class="dictionary">Used to tag JEPs that have been superseded by a newer version of the JEP.</td> </tr> <tr> <td class="dictionary"><span id="jvmci"><span class="jbs-label">jvmci</span></span></td> <td class="dictionary">Used to identify issues in the JVM Compiler Interface.</td> </tr> <tr> <td class="dictionary"><span id="maintainer-pain"><span class="jbs-label">maintainer-pain</span></span></td> <td class="dictionary"> <p>Used to tag bugs that for some reason is wasting time or in other ways are causing pain for the OpenJDK maintainers. Examples of issues that could be considered a pain:</p> <ul> <li> <p>A bug that occurs frequently in testing, maybe on a specific platform, maybe specific to one vendor’s test infrastructure, and requires that many maintainers investigate the failure in different test runs just to realize it’s the same issue as has been seen and reported before, or worse, don’t realize it’s a known issue and file a duplicate bug in JBS.</p> </li> <li> <p>Bugs that cause tests to fail without a proper explanation causing several maintainers to investigate the failures just to realize there is no information to be found.</p> </li> <li> <p>An underlying bug that causes several tests to fail intermittently.</p> </li> <li> <p>A bug that causes a test failure in a faraway place and the failure isn’t acted on quickly.</p> </li> </ul> <p>There are other cases as well and there is some flexibility in the definition. If you see a problem that is causing pain for a large number of maintainers, add an explanation in the JBS issue to why you think the issue is a pain and add the label.</p> <p>If you have a <span class="jbs-label">maintainer-pain</span> bug assigned to you please consider fixing it asap. If you chose not to work on the issue, you should at least be aware that you are choosing to waste others’ time and people will be affected by this choice.</p> As with any issue the best way to deal with a <span class="jbs-label">maintainer-pain</span> issue is to fix it. Another way to reduce the noise is to <a href="#excluding-a-test">exclude the failing test</a>. This is a viable option if there is a limited set of tests that are failing and the bug is actively investigated. When excluding a <span class="jbs-label">maintainer-pain</span> issue, remember to move the <span class="jbs-label">maintainer-pain</span> label to the JBS issue used to exclude. Leaving the label on the closed exclude-issue is helpful for tracking purposes.</td> </tr> <tr> <td class="dictionary"><span id="noreg"><span class="jbs-label">noreg-</span><code>.*</code></span><br /> <span id="nounit"><span class="jbs-label">nounit-</span><code>.*</code></span></td> <td class="dictionary"> <p>The <span class="jbs-label">noreg-</span><code>.*</code> and <span class="jbs-label">nounit-</span><code>.*</code> labels are used to explain why a bugfix doesn’t need/have a regression test or a unit test. The suffix of the label is described below.</p> <p>Please note that the <span class="jbs-label">noreg-</span> namespace is closed, meaning that no new <span class="jbs-label">noreg-</span> labels should be added unless properly motivated, discussed, and agreed upon.</p> <dl> <dt><span id="noreg-sqe"><span class="jbs-label">-sqe</span></span></dt> <dd>Change can be verified by running an existing SQE test suite; the bug should identify the suite and the specific test case(s).</dd> <dt><span id="noreg-jck"><span class="jbs-label">-jck</span></span></dt> <dd>Change can be verified by running the JCK; the bug should identify the specific test case(s).</dd> <dt><span id="noreg-external"><span class="jbs-label">-external</span></span></dt> <dd>Change can be verified by running an existing external test suite; the bug should identify the suite and the specific test case(s).</dd> <dt><span id="noreg-doc"><span class="jbs-label">-doc</span></span></dt> <dd>Change only affects documentation.</dd> <dt><span id="noreg-demo"><span class="jbs-label">-demo</span></span></dt> <dd>Change only affects demo code.</dd> <dt><span id="noreg-build"><span class="jbs-label">-build</span></span></dt> <dd>Change only affects build infrastructure (makefiles, copyrights, scripts, etc.).</dd> <dt><span id="noreg-self"><span class="jbs-label">-self</span></span></dt> <dd>Change is a fix to a regression or unit test itself.</dd> <dt><span id="noreg-perf"><span class="jbs-label">-perf</span></span></dt> <dd>Change is for a performance bug for which writing a regression test is infeasible; the bug should describe how to verify the fix.</dd> <dt><span id="noreg-hard"><span class="jbs-label">-hard</span></span></dt> <dd>It’s too hard to write a regression or unit test for this bug (e.g., theoretical race condition, complex setup, reboot required, editing of installed files required, specific graphics card required); the bug should explain why.</dd> <dt><span id="noreg-long"><span class="jbs-label">-long</span></span></dt> <dd>Testing requires a very long running-time (e.g., more than a few minutes).</dd> <dt><span id="noreg-big"><span class="jbs-label">-big</span></span></dt> <dd>Testing requires an unreasonable quantity of resources (e.g., tens of gigabytes of filesystem space).</dd> <dt><span id="noreg-trivial"><span class="jbs-label">-trivial</span></span></dt> <dd>Change is so trivial that nothing could possibly go wrong with it.</dd> <dt><span id="noreg-cleanup"><span class="jbs-label">-cleanup</span></span></dt> <dd>Change is a cleanup or refactoring of existing code that is covered by existing tests.</dd> <dt><span id="noreg-l10n"><span class="jbs-label">-l10n</span></span></dt> <dd>Change only affects localized text.</dd> <dt><span id="noreg-undo"><span class="jbs-label">-undo</span></span></dt> <dd>Change is a reversion of a previous faulty change.</dd> <dt><span id="noreg-other"><span class="jbs-label">-other</span></span></dt> <dd>Regression or unit test is unnecessary or infeasible for some other reason; the bug report should explain why.</dd> </dl> Examples: If a bug fix only corrects a change in the build system, then add the <span class="jbs-label">noreg-build</span> label to the corresponding bug. If the change improves loop optimizations in HotSpot, then add <span class="jbs-label">nounit-perf</span> to the corresponding bug.</td> </tr> <tr> <td class="dictionary"><span id="performance"><span class="jbs-label">performance</span></span></td> <td class="dictionary">Used to identify an issue with noticeable performance impact. Either positive or negative.</td> </tr> <tr> <td class="dictionary"><span id="pit"><span class="jbs-label"><del>pit</del></span></span></td> <td class="dictionary"><strong>Deprecated.</strong> Was used to indicate that a failure happened in product integration testing (PIT). Since we are now running tiered testing there is no more PIT. See <span class="jbs-label">tier</span><code>[1-8]</code>.</td> </tr> <tr> <td class="dictionary"><span id="problemlist"><span class="jbs-label">problemlist</span></span></td> <td class="dictionary">One or more tests has been problem-listed due to this bug.</td> </tr> <tr> <td class="dictionary"><span id="regression"><span class="jbs-label">regression</span></span></td> <td class="dictionary">Used to identify regressions. A regression is where behavior has <em>incorrectly</em> changed from a previous build or release. Ideally all regressions are identified and fixed before they are released, if not they must be fixed at latest in the following release after they are identified. All regressions must have the <span class="jbs-field">Affects Version/s</span> set.</td> </tr> <tr> <td class="dictionary"><span id="regression_id"><span class="jbs-label">regression_</span><em>(ID)</em></span></td> <td class="dictionary">Used to identify the fix that caused the regression, where known.</td> </tr> <tr> <td class="dictionary"><span id="release-note"><span class="jbs-label">release-note</span></span></td> <td class="dictionary">Used to indicate that the issue is a release note. See <a href="#release-notes">Release Notes</a>.</td> </tr> <tr> <td class="dictionary"><span id="release-note-yes"><span class="jbs-label">release-note=yes</span></span><br /> <span id="release-note-no"><span class="jbs-label">release-note=no</span></span><br /> <span id="release-note-done"><span class="jbs-label"><del>release-note=done</del></span></span></td> <td class="dictionary"> <p>Used to indicate whether a change requires a release note or not. The labels are always placed on the main JBS issue, never on the actual release note issue. See <a href="#release-notes">Release Notes</a>.</p> <span class="jbs-label">release-note=done</span> is deprecated and should no longer be used.</td> </tr> <tr> <td class="dictionary"><span id="rn"><span class="jbs-label">RN-</span><code>.*</code></span></td> <td class="dictionary">Used to indicate what kind of change the release note is for. See <a href="#release-notes">Release Notes</a>.</td> </tr> <tr> <td class="dictionary"><span id="starter"><span class="jbs-label">starter</span></span></td> <td class="dictionary">A starter bug is a well contained, small issue that is suitable for someone new to the codebase.</td> </tr> <tr> <td class="dictionary"><span id="startup"><span class="jbs-label">startup</span></span></td> <td class="dictionary">Used to identify an issue as affecting Java SE startup performance. Issues with this label should also have a <span class="jbs-label">performance</span> label.</td> </tr> <tr> <td class="dictionary"><span id="tck-red-rel"><span class="jbs-label">tck-red-</span><em>(Rel)</em></span><br /> <span id="tck-red"><span class="jbs-label"><del>tck-red</del></span></span></td> <td class="dictionary"> <p>Used to identify TCK conformance stoppers (e.g. failure of a valid TCK test that exists in a shipped TCK). The release number indicates which release of the TCK that failed. E.g., <span class="jbs-label">tck-red-11</span></p> <p>If an issue with a <span class="jbs-label">tck-red-</span><em>(Rel)</em> label is closed as a <span class="jbs-value">Duplicate</span>, the label <strong>must</strong> be added to the duplicating issue as well.</p> There are <span class="jbs-label">tck-red</span> labels without the release number out there as well. This usage is deprecated.</td> </tr> <tr> <td class="dictionary"><span id="test"><span class="jbs-label"><del>test</del></span></span><br /> <span id="test-only"><span class="jbs-label"><del>test-only</del></span></span><br /> <span id="testbug"><span class="jbs-label"><del>testbug</del></span></span></td> <td class="dictionary">The labels <span class="jbs-label">test</span>, <span class="jbs-label">test-only</span>, and <span class="jbs-label">testbug</span> are deprecated and should no longer be used. Use <a href="#noreg"><span class="jbs-label">noreg-self</span></a> to indicate that an issue is a bug in test code.</td> </tr> <tr> <td class="dictionary"><span id="tier"><span class="jbs-label">tier</span><code>[1-8]</code></span></td> <td class="dictionary"> <p>Used to indicate which tier in the <code>jdk/jdk</code> CI pipeline a test failure has been seen in. Lower tiers would in general mean higher urgency to fix the issue. E.g., <span class="jbs-label">tier1</span>, <span class="jbs-label">tier2</span></p> Please note that these labels are reserved for bugs seen in the <code>jdk/jdk</code> CI pipeline. Use <em>(Rel)</em><span class="jbs-label">-tier</span><code>[1-8]</code> for other CI pipelines, where <em>(Rel)</em> is the name of the pipeline. E.g. <span class="jbs-label">8u-tier1</span></td> </tr> <tr> <td class="dictionary"><span id="webbug"><span class="jbs-label">webbug</span></span></td> <td class="dictionary">Used to identify a bug as submitted on <a href="https://bugs.java.com/bugdatabase/">bugs.java.com</a>.</td> </tr> <tr> <td class="dictionary"><span id="zgc"><span class="jbs-label">zgc</span></span></td> <td class="dictionary">Used to identify an issue in ZGC.</td> </tr> </table> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="cloning-the-jdk">Cloning the JDK</h1> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://github.com/openjdk/jdk">OpenJDK Mainline GitHub project</a></li> <li><a href="https://wiki.openjdk.org/display/SKARA">Skara Documentation</a></li> </ul> </div> <p>After the initial release of the JDK source code into OpenJDK in 2007 the OpenJDK project moved from TeamWare to using Mercurial. Starting in 2019 the source revision control has been moved to Git. The complete source code for the JDK is today hosted at <a href="https://github.com">GitHub</a>. You can browse the code directly in the <a href="https://github.com/openjdk/jdk">openjdk/jdk repository</a>, or download the code for offline browsing, editing, and building using <code>git clone</code>.</p> <pre><code>$ git clone https://github.com/openjdk/jdk.git</code></pre> <p><code>openjdk/jdk</code> is the mainline JDK development repository where the next major release of the JDK is being developed. Other <a href="https://openjdk.org/bylaws#project">Projects</a> have their own repositories on <a href="https://github.com/openjdk">GitHub</a>.</p> <div class="note"> <p>Note that source may be available from other locations, for example <code>src.zip</code> from a full JDK distribution. However, OpenJDK contributions must use source from the appropriate <a href="https://github.com/openjdk">OpenJDK GitHub repository</a> since other source distributions may contain older code or code which differs due to licensing. Consult the Project’s documentation or <a href="#mailing-lists">mailing lists</a> to determine the appropriate repository, development conventions, and helpful tools.</p> </div> <p>If you intend to contribute patches, you should first <em>fork</em> the repository on <a href="https://github.com">GitHub</a> and clone your own <em>personal fork</em> as shown below. To fork a <a href="https://openjdk.org/bylaws#project">Project</a> on <a href="https://github.com">GitHub</a>, go to the GitHub Project page and click the ‘Fork’ button in the upper right corner, then follow the on screen instructions.</p> <p>This is the typical development model:</p> <div style="text-align:center;"> <div class="figure"><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibWVybWFpZC0xNzM4MTkwNjU0OTE0IiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgaGVpZ2h0PSIzMTguNSIgc3R5bGU9Im1heC13aWR0aDogMjA5Ljc1OHB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9IjAgMCAyMDkuNzU3ODEyNSAzMTguNSI+PHN0eWxlPiNtZXJtYWlkLTE3MzgxOTA2NTQ5MTQge2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTZweDtmaWxsOiMwMDAwMDA7fSNtZXJtYWlkLTE3MzgxOTA2NTQ5MTQgLmVycm9yLWljb257ZmlsbDojNTUyMjIyO30jbWVybWFpZC0xNzM4MTkwNjU0OTE0IC5lcnJvci10ZXh0e2ZpbGw6IzU1MjIyMjtzdHJva2U6IzU1MjIyMjt9I21lcm1haWQtMTczODE5MDY1NDkxNCAuZWRnZS10aGlja25lc3Mtbm9ybWFse3N0cm9rZS13aWR0aDoycHg7fSNtZXJtYWlkLTE3MzgxOTA2NTQ5MTQgLmVkZ2UtdGhpY2tuZXNzLXRoaWNre3N0cm9rZS13aWR0aDozLjVweDt9I21lcm1haWQtMTczODE5MDY1NDkxNCAuZWRnZS1wYXR0ZXJuLXNvbGlke3N0cm9rZS1kYXNoYXJyYXk6MDt9I21lcm1haWQtMTczODE5MDY1NDkxNCAuZWRnZS1wYXR0ZXJuLWRhc2hlZHtzdHJva2UtZGFzaGFycmF5OjM7fSNtZXJtYWlkLTE3MzgxOTA2NTQ5MTQgLmVkZ2UtcGF0dGVybi1kb3R0ZWR7c3Ryb2tlLWRhc2hhcnJheToyO30jbWVybWFpZC0xNzM4MTkwNjU0OTE0IC5tYXJrZXJ7ZmlsbDojNjY2O3N0cm9rZTojNjY2O30jbWVybWFpZC0xNzM4MTkwNjU0OTE0IC5tYXJrZXIuY3Jvc3N7c3Ryb2tlOiM2NjY7fSNtZXJtYWlkLTE3MzgxOTA2NTQ5MTQgc3Zne2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTZweDt9I21lcm1haWQtMTczODE5MDY1NDkxNCAubGFiZWx7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2NvbG9yOiMwMDAwMDA7fSNtZXJtYWlkLTE3MzgxOTA2NTQ5MTQgLmNsdXN0ZXItbGFiZWwgdGV4dHtmaWxsOiMzMzM7fSNtZXJtYWlkLTE3MzgxOTA2NTQ5MTQgLmNsdXN0ZXItbGFiZWwgc3Bhbntjb2xvcjojMzMzO30jbWVybWFpZC0xNzM4MTkwNjU0OTE0IC5sYWJlbCB0ZXh0LCNtZXJtYWlkLTE3MzgxOTA2NTQ5MTQgc3BhbntmaWxsOiMwMDAwMDA7Y29sb3I6IzAwMDAwMDt9I21lcm1haWQtMTczODE5MDY1NDkxNCAubm9kZSByZWN0LCNtZXJtYWlkLTE3MzgxOTA2NTQ5MTQgLm5vZGUgY2lyY2xlLCNtZXJtYWlkLTE3MzgxOTA2NTQ5MTQgLm5vZGUgZWxsaXBzZSwjbWVybWFpZC0xNzM4MTkwNjU0OTE0IC5ub2RlIHBvbHlnb24sI21lcm1haWQtMTczODE5MDY1NDkxNCAubm9kZSBwYXRoe2ZpbGw6I2VlZTtzdHJva2U6Izk5OTtzdHJva2Utd2lkdGg6MXB4O30jbWVybWFpZC0xNzM4MTkwNjU0OTE0IC5ub2RlIC5sYWJlbHt0ZXh0LWFsaWduOmNlbnRlcjt9I21lcm1haWQtMTczODE5MDY1NDkxNCAubm9kZS5jbGlja2FibGV7Y3Vyc29yOnBvaW50ZXI7fSNtZXJtYWlkLTE3MzgxOTA2NTQ5MTQgLmFycm93aGVhZFBhdGh7ZmlsbDojMzMzMzMzO30jbWVybWFpZC0xNzM4MTkwNjU0OTE0IC5lZGdlUGF0aCAucGF0aHtzdHJva2U6IzY2NjtzdHJva2Utd2lkdGg6Mi4wcHg7fSNtZXJtYWlkLTE3MzgxOTA2NTQ5MTQgLmZsb3djaGFydC1saW5re3N0cm9rZTojNjY2O2ZpbGw6bm9uZTt9I21lcm1haWQtMTczODE5MDY1NDkxNCAuZWRnZUxhYmVse2JhY2tncm91bmQtY29sb3I6d2hpdGU7dGV4dC1hbGlnbjpjZW50ZXI7fSNtZXJtYWlkLTE3MzgxOTA2NTQ5MTQgLmVkZ2VMYWJlbCByZWN0e29wYWNpdHk6MC41O2JhY2tncm91bmQtY29sb3I6d2hpdGU7ZmlsbDp3aGl0ZTt9I21lcm1haWQtMTczODE5MDY1NDkxNCAuY2x1c3RlciByZWN0e2ZpbGw6aHNsKDAsIDAlLCA5OC45MjE1Njg2Mjc1JSk7c3Ryb2tlOiM3MDcwNzA7c3Ryb2tlLXdpZHRoOjFweDt9I21lcm1haWQtMTczODE5MDY1NDkxNCAuY2x1c3RlciB0ZXh0e2ZpbGw6IzMzMzt9I21lcm1haWQtMTczODE5MDY1NDkxNCAuY2x1c3RlciBzcGFue2NvbG9yOiMzMzM7fSNtZXJtYWlkLTE3MzgxOTA2NTQ5MTQgZGl2Lm1lcm1haWRUb29sdGlwe3Bvc2l0aW9uOmFic29sdXRlO3RleHQtYWxpZ246Y2VudGVyO21heC13aWR0aDoyMDBweDtwYWRkaW5nOjJweDtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjEycHg7YmFja2dyb3VuZDpoc2woLTE2MCwgMCUsIDkzLjMzMzMzMzMzMzMlKTtib3JkZXI6MXB4IHNvbGlkICM3MDcwNzA7Ym9yZGVyLXJhZGl1czoycHg7cG9pbnRlci1ldmVudHM6bm9uZTt6LWluZGV4OjEwMDt9I21lcm1haWQtMTczODE5MDY1NDkxNCA6cm9vdHstLW1lcm1haWQtZm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO308L3N0eWxlPjxnPjxnIGNsYXNzPSJvdXRwdXQiPjxnIGNsYXNzPSJjbHVzdGVycyI+PGcgY2xhc3M9ImNsdXN0ZXIiIGlkPSJmbG93Y2hhcnQtR2l0SHViLTIwIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMDQuODc4OTA2MjUsMTA1Ljc1KSIgc3R5bGU9Im9wYWNpdHk6IDE7Ij48cmVjdCB3aWR0aD0iMTkzLjc1NzgxMjUiIGhlaWdodD0iMTk1LjUiIHg9Ii05Ni44Nzg5MDYyNSIgeT0iLTk3Ljc1Ij48L3JlY3Q+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAtODMuNzUpIiBpZD0ibWVybWFpZC0xNzM4MTkwNjU0OTE0VGV4dCI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTI0LjkyNTc4MTI1LC05LjI1KSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjQ5Ljg1MTU2MjUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkdpdEh1YjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VQYXRocyI+PGcgY2xhc3M9ImVkZ2VQYXRoIExTLXVwc3RyZWFtIExFLWZvcmsiIGlkPSJMLXVwc3RyZWFtLWZvcmsiIHN0eWxlPSJvcGFjaXR5OiAxOyI+PHBhdGggY2xhc3M9InBhdGgiIGQ9Ik05My42Mzc1NTg0MTEyMTQ5NSw3MS41TDkwLjMwNDA4NTEzNDM0NTgxLDc3LjIwODMzMzMzMzMzMzMzQzg2Ljk3MDYxMTg1NzQ3NjY0LDgyLjkxNjY2NjY2NjY2NjY3LDgwLjMwMzY2NTMwMzczODMzLDk0LjMzMzMzMzMzMzMzMzMzLDgwLjMwMzY2NTMwMzczODMzLDEwNS43NUM4MC4zMDM2NjUzMDM3MzgzMywxMTcuMTY2NjY2NjY2NjY2NjcsODYuOTcwNjExODU3NDc2NjQsMTI4LjU4MzMzMzMzMzMzMzM0LDkwLjMwNDA4NTEzNDM0NTc4LDEzNC4yOTE2NjY2NjY2NjY2Nkw5My42Mzc1NTg0MTEyMTQ5NSwxNDAiIG1hcmtlci1lbmQ9InVybCgjYXJyb3doZWFkMzgpIiBzdHlsZT0iZmlsbDpub25lIj48L3BhdGg+PGRlZnM+PG1hcmtlciBpZD0iYXJyb3doZWFkMzgiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iOSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InN0cm9rZVdpZHRoIiBtYXJrZXJXaWR0aD0iOCIgbWFya2VySGVpZ2h0PSI2IiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCAwIEwgMTAgNSBMIDAgMTAgeiIgY2xhc3M9ImFycm93aGVhZFBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ij48L3BhdGg+PC9tYXJrZXI+PC9kZWZzPjwvZz48ZyBjbGFzcz0iZWRnZVBhdGggTFMtZm9yayBMRS1sb2NhbCIgaWQ9IkwtZm9yay1sb2NhbCIgc3R5bGU9Im9wYWNpdHk6IDE7Ij48cGF0aCBjbGFzcz0icGF0aCIgZD0iTTkyLjUwNjk0MDc2NjI0MjkzLDE3OC41TDg5LjgyOTAyNjE1OTM2OTEsMTgyLjY2NjY2NjY2NjY2NjY2Qzg3LjE1MTExMTU1MjQ5NTMsMTg2LjgzMzMzMzMzMzMzMzM0LDgxLjc5NTI4MjMzODc0NzY0LDE5NS4xNjY2NjY2NjY2NjY2Niw3OS4xMTczNjc3MzE4NzM4MSwyMDUuMDQxNjY2NjY2NjY2NjZDNzYuNDM5NDUzMTI1LDIxNC45MTY2NjY2NjY2NjY2Niw3Ni40Mzk0NTMxMjUsMjI2LjMzMzMzMzMzMzMzMzM0LDc5LjQ3Mzg4MDc1NTkzODQ4LDIzNy43NUM4Mi41MDgzMDgzODY4NzY5NSwyNDkuMTY2NjY2NjY2NjY2NjYsODguNTc3MTYzNjQ4NzUzOTEsMjYwLjU4MzMzMzMzMzMzMzMsOTEuNjExNTkxMjc5NjkyMzgsMjY2LjI5MTY2NjY2NjY2NjdMOTQuNjQ2MDE4OTEwNjMwODQsMjcyIiBtYXJrZXItZW5kPSJ1cmwoI2Fycm93aGVhZDM5KSIgc3R5bGU9ImZpbGw6bm9uZSI+PC9wYXRoPjxkZWZzPjxtYXJrZXIgaWQ9ImFycm93aGVhZDM5IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJzdHJva2VXaWR0aCIgbWFya2VyV2lkdGg9IjgiIG1hcmtlckhlaWdodD0iNiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgMCBMIDEwIDUgTCAwIDEwIHoiIGNsYXNzPSJhcnJvd2hlYWRQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyI+PC9wYXRoPjwvbWFya2VyPjwvZGVmcz48L2c+PGcgY2xhc3M9ImVkZ2VQYXRoIExTLWxvY2FsIExFLWZvcmsiIGlkPSJMLWxvY2FsLWZvcmsiIHN0eWxlPSJvcGFjaXR5OiAxOyI+PHBhdGggY2xhc3M9InBhdGgiIGQ9Ik0xMTguNzA5OTI0NDMwNDkwNjYsMjcyTDEyMi44MTEzMzAyNTQ1NzU1NCwyNjYuMjkxNjY2NjY2NjY2N0MxMjYuOTEyNzM2MDc4NjYwNDQsMjYwLjU4MzMzMzMzMzMzMzMsMTM1LjExNTU0NzcyNjgzMDIxLDI0OS4xNjY2NjY2NjY2NjY2NiwxMzkuMjE2OTUzNTUwOTE1MTIsMjM3Ljc1QzE0My4zMTgzNTkzNzUsMjI2LjMzMzMzMzMzMzMzMzM0LDE0My4zMTgzNTkzNzUsMjE0LjkxNjY2NjY2NjY2NjY2LDEzOS42OTg4MjUxODI0Mzg4LDIwNS4wNDE2NjY2NjY2NjY2NkMxMzYuMDc5MjkwOTg5ODc3NiwxOTUuMTY2NjY2NjY2NjY2NjYsMTI4Ljg0MDIyMjYwNDc1NTE4LDE4Ni44MzMzMzMzMzMzMzMzNCwxMjUuMjIwNjg4NDEyMTkzOTgsMTgyLjY2NjY2NjY2NjY2NjY2TDEyMS42MDExNTQyMTk2MzI3OCwxNzguNSIgbWFya2VyLWVuZD0idXJsKCNhcnJvd2hlYWQ0MCkiIHN0eWxlPSJmaWxsOm5vbmUiPjwvcGF0aD48ZGVmcz48bWFya2VyIGlkPSJhcnJvd2hlYWQ0MCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI5IiByZWZZPSI1IiBtYXJrZXJVbml0cz0ic3Ryb2tlV2lkdGgiIG1hcmtlcldpZHRoPSI4IiBtYXJrZXJIZWlnaHQ9IjYiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDAgTCAxMCA1IEwgMCAxMCB6IiBjbGFzcz0iYXJyb3doZWFkUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiPjwvcGF0aD48L21hcmtlcj48L2RlZnM+PC9nPjxnIGNsYXNzPSJlZGdlUGF0aCBMUy1mb3JrIExFLXVwc3RyZWFtIiBpZD0iTC1mb3JrLXVwc3RyZWFtIiBzdHlsZT0ib3BhY2l0eTogMTsiPjxwYXRoIGNsYXNzPSJwYXRoIiBkPSJNMTE3LjA2OTY4Mjc1NDA4ODc5LDE0MEwxMjAuNjg0Njk2NTY1OTA3MzIsMTM0LjI5MTY2NjY2NjY2NjY2QzEyNC4yOTk3MTAzNzc3MjU4NCwxMjguNTgzMzMzMzMzMzMzMzQsMTMxLjUyOTczODAwMTM2MjkyLDExNy4xNjY2NjY2NjY2NjY2NywxMzEuNTI5NzM4MDAxMzYyOTQsMTA1Ljc1QzEzMS41Mjk3MzgwMDEzNjI5Miw5NC4zMzMzMzMzMzMzMzMzMywxMjQuMjk5NzEwMzc3NzI1ODQsODIuOTE2NjY2NjY2NjY2NjcsMTIwLjY4NDY5NjU2NTkwNzMyLDc3LjIwODMzMzMzMzMzMzMzTDExNy4wNjk2ODI3NTQwODg3OSw3MS41IiBtYXJrZXItZW5kPSJ1cmwoI2Fycm93aGVhZDQxKSIgc3R5bGU9ImZpbGw6bm9uZSI+PC9wYXRoPjxkZWZzPjxtYXJrZXIgaWQ9ImFycm93aGVhZDQxIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJzdHJva2VXaWR0aCIgbWFya2VyV2lkdGg9IjgiIG1hcmtlckhlaWdodD0iNiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgMCBMIDEwIDUgTCAwIDEwIHoiIGNsYXNzPSJhcnJvd2hlYWRQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyI+PC9wYXRoPjwvbWFya2VyPjwvZGVmcz48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWxzIj48ZyBjbGFzcz0iZWRnZUxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg3My42MzY3MTg3NSwxMDUuNzUpIiBzdHlsZT0ib3BhY2l0eTogMTsiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNC4zOTQ1MzEyNSwtOS4yNSkiIGNsYXNzPSJsYWJlbCI+PHJlY3Qgcng9IjAiIHJ5PSIwIiB3aWR0aD0iMjguNzg5MDYyNSIgaGVpZ2h0PSIxOC41Ij48L3JlY3Q+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjI4Ljc4OTA2MjUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGlkPSJMLUwtdXBzdHJlYW0tZm9yayIgY2xhc3M9ImVkZ2VMYWJlbCBMLUxTLXVwc3RyZWFtJyBMLUxFLWZvcmsiPmZvcms8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNzYuNDM5NDUzMTI1LDIzNy43NSkiIHN0eWxlPSJvcGFjaXR5OiAxOyI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTE5LjM0NzY1NjI1LC05LjI1KSIgY2xhc3M9ImxhYmVsIj48cmVjdCByeD0iMCIgcnk9IjAiIHdpZHRoPSIzOC42OTUzMTI1IiBoZWlnaHQ9IjE4LjUiPjwvcmVjdD48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMzguNjk1MzEyNSIgaGVpZ2h0PSIxOC41Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gaWQ9IkwtTC1mb3JrLWxvY2FsIiBjbGFzcz0iZWRnZUxhYmVsIEwtTFMtZm9yaycgTC1MRS1sb2NhbCI+Y2xvbmU8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTQzLjMxODM1OTM3NSwyMzcuNzUpIiBzdHlsZT0ib3BhY2l0eTogMTsiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNi40Mzc1LC05LjI1KSIgY2xhc3M9ImxhYmVsIj48cmVjdCByeD0iMCIgcnk9IjAiIHdpZHRoPSIzMi44NzUiIGhlaWdodD0iMTguNSI+PC9yZWN0Pjxmb3JlaWduT2JqZWN0IHdpZHRoPSIzMi44NzUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGlkPSJMLUwtbG9jYWwtZm9yayIgY2xhc3M9ImVkZ2VMYWJlbCBMLUxTLWxvY2FsJyBMLUxFLWZvcmsiPnB1c2g8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTM4Ljc1OTc2NTYyNSwxMDUuNzUpIiBzdHlsZT0ib3BhY2l0eTogMTsiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC05LjExNzE4NzUsLTkuMjUpIiBjbGFzcz0ibGFiZWwiPjxyZWN0IHJ4PSIwIiByeT0iMCIgd2lkdGg9IjE4LjIzNDM3NSIgaGVpZ2h0PSIxOC41Ij48L3JlY3Q+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjE4LjIzNDM3NSIgaGVpZ2h0PSIxOC41Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gaWQ9IkwtTC1mb3JrLXVwc3RyZWFtIiBjbGFzcz0iZWRnZUxhYmVsIEwtTFMtZm9yaycgTC1MRS11cHN0cmVhbSI+UFI8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjxnIGNsYXNzPSJub2RlcyI+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCIgaWQ9ImZsb3djaGFydC11cHN0cmVhbS0xMCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTA0Ljg3ODkwNjI1LDUyLjI1KSIgc3R5bGU9Im9wYWNpdHk6IDE7Ij48cmVjdCByeD0iNSIgcnk9IjUiIHg9Ii01NC41MzEyNSIgeT0iLTE5LjI1IiB3aWR0aD0iMTA5LjA2MjUiIGhlaWdodD0iMzguNSIgY2xhc3M9ImxhYmVsLWNvbnRhaW5lciI+PC9yZWN0PjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwwKSI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQ0LjUzMTI1LC05LjI1KSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9Ijg5LjA2MjUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPm9wZW5qZGsvamRrPC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQiIGlkPSJmbG93Y2hhcnQtZm9yay0xMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTA0Ljg3ODkwNjI1LDE1OS4yNSkiIHN0eWxlPSJvcGFjaXR5OiAxOyI+PHJlY3Qgcng9IjUiIHJ5PSI1IiB4PSItNjEuODc4OTA2MjUiIHk9Ii0xOS4yNSIgd2lkdGg9IjEyMy43NTc4MTI1IiBoZWlnaHQ9IjM4LjUiIGNsYXNzPSJsYWJlbC1jb250YWluZXIiPjwvcmVjdD48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsMCkiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01MS44Nzg5MDYyNSwtOS4yNSkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIxMDMuNzU3ODEyNSIgaGVpZ2h0PSIxOC41Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+T3BlbkR1a2UvamRrPC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQiIGlkPSJmbG93Y2hhcnQtbG9jYWwtMTUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEwNC44Nzg5MDYyNSwyOTEuMjUpIiBzdHlsZT0ib3BhY2l0eTogMTsiPjxyZWN0IHJ4PSI1IiByeT0iNSIgeD0iLTI3LjE3NTc4MTI1IiB5PSItMTkuMjUiIHdpZHRoPSI1NC4zNTE1NjI1IiBoZWlnaHQ9IjM4LjUiIGNsYXNzPSJsYWJlbC1jb250YWluZXIiPjwvcmVjdD48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsMCkiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNy4xNzU3ODEyNSwtOS4yNSkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIzNC4zNTE1NjI1IiBoZWlnaHQ9IjE4LjUiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5sb2NhbDwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=" alt="" /> <p class="caption">Diagram of upstream repos and user's clone</p> </div> </div> <p>Pushes to your personal fork can be made either using HTTPS or SSH. These examples assume you have an SSH key installed on <a href="https://github.com">GitHub</a>. If this is the first time you clone your personal fork of an OpenJDK repository you may want to create an SSH key to use with it. See <a href="#generating-an-ssh-key">Generating an SSH key</a> below. Once you have your personal fork and an SSH key to go with it, go ahead and clone.</p> <pre><code>$ git clone git@github.com:OpenDuke/jdk.git $ cd jdk $ git remote add upstream https://github.com/openjdk/jdk.git</code></pre> <p>In the example above Duke cloned his personal fork of the JDK mainline repository using SSH. You should of course use your own <a href="https://github.com">GitHub</a> username instead. Then, by adding a new <em>remote</em> named ‘upstream’, the clone is associated with <a href="https://github.com/openjdk/jdk">openjdk/jdk</a>. Doing this will allow the tooling to automatically create a PR on <a href="https://github.com/openjdk/jdk">openjdk/jdk</a> whenever a change is pushed to the personal fork. The way that works is that once the change has been pushed to the personal fork, and you navigate to the <a href="https://github.com/openjdk/jdk">openjdk/jdk</a> repository on <a href="https://github.com">GitHub</a>, there will be a message saying that you just pushed a change and asking if you want to create a PR.</p> <h2 id="working-with-git-branches">Working with git branches</h2> <p>It is <strong>strongly</strong> recommended to always create a new branch for any change you intend to implement. If your PR gets accepted, it will be squashed and pushed by the OpenJDK bots. This means that if you make changes to your <code>master</code> branch, it will diverge from the upstream <code>master</code> branch. This in turn means that your repo will forever be out of sync with the upstream repo, which will cause merge conflicts every single time you want to update your repo from upstream. Having a separate branch for each change also means that you can easily work on many different changes in parallel in the same code repository. Unless you know what you are doing, the recommendation is also to always base your new branch on the <code>master</code> branch.</p> <pre><code>$ git switch -c JDK-8272373 master</code></pre> <p>Here we create a new branch called <code>JDK-8272373</code> based on the <code>master</code> branch and set the repository up to work in that new branch.</p> <p>If you intend to work on a backport to a feature release stabilization branch, your new local branch should of course be based on the stabilization branch instead of <code>master</code>.</p> <pre><code>$ git switch -c JDK-8272373 jdk23</code></pre> <p><code>git switch</code> was introduced in Git version 2.23. For earlier versions of Git <code>git checkout</code> can be used instead. However it is always recommended to use the latest versions of all your tools when possible.</p> <div class="note"> <p>More information about how to work with git and the dedicated tooling that is available for OpenJDK can be found in the <a href="https://wiki.openjdk.org/display/SKARA">Project Skara Documentation</a>. If you’re new to git you can also read more about how to work with it in one of the many fine git tutorials available on the Internet. For instance the <a href="https://git-scm.com/book/en/v2">Pro Git book</a>. This guide doesn’t aspire to become another git guide.</p> </div> <h2 id="generating-an-ssh-key">Generating an SSH key</h2> <p>For security reasons you should always create new keys and use different keys with each repository you clone. The <code>ssh-keygen</code> command generates an SSH key. The <code>-t</code> option determines which type of key to create. <code>ed25519</code> is recommended. <code>-C</code> is used to add a comment in the key file, to help you remember which key it is. While it’s possible to use SSH without a passphrase, this is <strong>strongly discouraged</strong>. Empty or insecure passphrases may be reset using <code>ssh-keygen -p</code>; this doesn’t change the keys.</p> <pre><code>$ ssh-keygen -t ed25519 -C openjdk-jdk -f ~/.ssh/openjdk-jdk Generating public/private ed25519 key pair. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /Users/duke/.ssh/openjdk-jdk. Your public key has been saved in /Users/duke/.ssh/openjdk-jdk.pub. The key fingerprint is: SHA256:WS4jCQMtat75ZEue+so+Lgj7V/sdMtj1FTNkfNsCfHA openjdk-jdk The key's randomart image is: +--[ED25519 256]--+ | .. ..oE | | ... o+o .| | . .o . o+.o| |.. o . + .=.| |o . . o S o .. | |.. o +.+ + . . | |o. *.+.+ . . | |o....=. + . | | .=B=. .. . | +----[SHA256]-----+</code></pre> <p><code>~/.ssh/openjdk-jdk</code> is a text file containing your private ssh key. There’s a corresponding public key in <code>~/.ssh/openjdk-jdk.pub</code> (as detailed in the example above). You should <strong>never</strong> share your private key. The <em>public</em> key on the other hand should be uploaded to <a href="https://github.com">GitHub</a>. Follow the steps below to do that.</p> <ul> <li>Go to the GitHub settings for your account by choosing “Settings” in the menu by your avatar in the upper right corner</li> <li>Go to “SSH and GPG keys”</li> <li>Click “New SSH key”</li> <li>Title “OpenJDK” (or something else appropriate)</li> <li>Paste the content of <code>~/.ssh/openjdk-jdk.pub</code> into the text field <ul> <li>To get the content of the file you can for instance use <code>cat ~/.ssh/openjdk-jdk.pub</code></li> <li>It will look something like this: <code>ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO8+egiIgWV+tE7LVVJmlR7WS2Lr3Fj7dXVo9HiasD6T openjdk-jdk</code></li> </ul> </li> <li>Click “Add SSH key”</li> </ul> <p>Now you are ready to clone your <a href="https://github.com/openjdk/jdk">openjdk/jdk</a> fork using SSH.</p> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="making-a-change">Making a Change</h1> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://wiki.openjdk.org/display/csr/Main">CSR Wiki</a></li> </ul> </div> <p>In case you jumped directly here and skipped reading the earlier sections of this guide, please keep in mind that there’s a lot more to it than just making a change in the code and submit a PR to GitHub. The list below shows the bare minimum required before a change can be accepted into OpenJDK.</p> <ol> <li><strong>Discuss the intended change</strong> – See <a href="#contributing-to-an-openjdk-project">Contributing to an OpenJDK Project</a></li> <li><strong>Make sure an issue id exists for the work</strong> – See <a href="#filing-an-issue">Filing an issue</a></li> <li><strong>Initiate a CSR request if your change have a compatibility impact</strong> – See <a href="#working-with-the-csr">Working with the CSR</a></li> <li><strong>Fix the issue</strong> – See <a href="#cloning-the-jdk">Cloning the JDK</a>, <a href="#working-with-git-branches">Working with git branches</a>, and <a href="#building-the-jdk">Building the JDK</a></li> <li><strong>Write regression tests and run relevant regression and unit tests on all relevant platforms</strong> – See <a href="#testing-the-jdk">Testing the JDK</a></li> <li><strong>Create a changeset</strong> – See <a href="#working-with-pull-requests">Working With Pull Requests</a></li> <li><strong>Update the bug content</strong> – See <a href="#updating-an-issue-while-fixing">Updating an issue while fixing</a></li> <li><strong>Request a review of the changes</strong> – See <a href="#life-of-a-pr">Life of a PR</a></li> <li><strong>Merge with the latest upstream changes and test again</strong></li> <li><strong>Integrate the changeset</strong> – See <a href="#working-with-pull-requests">Working With Pull Requests</a></li> <li><strong>Write a release note if appropriate</strong> – See <a href="#release-notes">Release Notes</a></li> </ol> <h2 id="working-with-the-csr">Working with the CSR</h2> <p>Changes that have a compatibility impact will require a separate approval besides the code review. This is handled through a <a href="https://wiki.openjdk.org/display/csr/Main">Compatibility and Specification Review</a>, a.k.a. CSR. Compatibility impact can be things like requiring a specification change, directly affect an external interface, changing command line options, or otherwise alter the behavior of the JDK in ways that could cause issues for users when upgrading to the next JDK version.</p> <p>See the <a href="https://wiki.openjdk.org/display/csr/Main">CSR wiki</a> for information on how to work through the CSR process.</p> <p>The CSR must be approved before the change is allowed to be integrated to a feature release or update release repository. Feature design and implementation work may begin concurrently with the CSR review, but may need to be modified in response to CSR feedback.</p> <h2 id="copyright-headers">Copyright Headers</h2> <p>All source code files in OpenJDK has a header with copyright statements and a license. Since this is legal documentation it shall not be updated or modified without seeking guidance from your legal representative. For that reason this guide can’t really give detailed information on what you can or should do. There are however a few generic things that can be clarified.</p> <p>This is an example copyright/license header:</p> <pre><code>/* * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */</code></pre> <p>This header has two copyright notices at the top (Oracle and SAP SE) and below them the license text.</p> <p>As stated in the header, don’t make changes to the copyright notices or the license text below them. If your affiliation has a copyright notice at the top of the header, consult your legal representative on how to update it. If your affiliation doesn’t have a copyright notice, again consult your legal representative to see if you should add one. Do not update a copyright notice if you don’t belong to that affiliation unless explicitly asked by the affiliation in question.</p> <p>If you create a new file, copy the license text from a nearby file. Do not add copyright notices for affiliations to which you don’t belong.</p> <p>If you move code from an existing file to a new file, bring the entire copyright + license header over to the new file.</p> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="building-the-jdk">Building the JDK</h1> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://openjdk.org/groups/build/doc/building.html">Official build instructions</a></li> <li><a href="https://github.com/openjdk/jdk">openjdk/jdk GitHub project</a></li> <li><a href="https://jdk.java.net/16/">JDK 16 General-Availability Release</a></li> </ul> </div> <p>The JDK build system is a fairly complex machine that has the ability to build anything from a single module to a complete shippable JDK bundle with various levels of debug capabilities, run tests, install your newly built JDK on your system, or cross-compile for some other system. The build uses <code>make</code> and a few other tools that you will have to install on your system before starting.</p> <p>The JDK supports incremental builds. This means that if you have a complete build and make changes in just a single part of the JDK (e.g. a module or part of the JVM), only that particular part needs to be rebuilt. So subsequent builds will be faster and you can always use a make target that results in a complete JDK image without having to worry about actually building the entire JDK every time. Please note that the incremental build do have limits in its understanding of what you change. For instance, if you change behaviors or conventions in one module there may be other parts of the JDK that implicitly depends on these without make’s knowledge. For this reason you may have to rebuild several modules, or do a clean build if you change things that may have a wider impact.</p> <p>The examples below show the steps taken to build the JDK source code. Please see <a href="#cloning-the-jdk">Cloning the JDK</a> for information on how to download it. These examples were written in the JDK 17 development time frame which is why the boot JDK used here is JDK 16. Note that the download links used here point to JDK 16 bundles. To build JDK N, use JDK N-1 as the boot JDK.</p> <p>The configure script will tell you what additional packages you need. In this first example several packages were needed since this build was performed on a clean Ubuntu installation. The configure script was run several times to get all the dependencies, but only the commands actually needed to get the JDK built are included in the log. This is just an example log, don’t copy the <code>apt-get install</code> line. Instead run <code>sh ./configure</code> to see what packages you actually need on your system.</p> <pre><code>$ wget https://download.java.net/java/GA/jdk16/7863447f0ab643c585b9bdebf67c69db/36/GPL/openjdk-16_linux-x64_bin.tar.gz $ tar xzf openjdk-16_linux-x64_bin.tar.gz $ sudo apt-get install autoconf zip make gcc g++ libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev libcups2-dev libfontconfig1-dev libasound2-dev $ cd jdk $ sh ./configure --with-boot-jdk=$HOME/jdk-16/ $ make images</code></pre> <p>The built JDK can be found in <code>build/linux-x86_64-server-release/jdk</code>. The exact path depends on your build platform and selected configuration.</p> <p>The second example is from a clean (newly installed) Mac running MacOS Big Sur. Please note that in this case there are some steps taken outside of the terminal. First XCode and the XCode command line tools must be installed. It could be that the most recent version of XCode that you get from App Store is too new to have been properly tested with the JDK build. See <a href="https://github.com/openjdk/jdk/blob/master/doc/building.md#apple-xcode"> the JDK build instructions</a> for supported versions and more details in case you need to install an older version of XCode. In this example <a href="https://www.macports.org">Mac Ports</a> is used to install <code>autoconf</code>. <code>autoconf</code> can also be installed using <a href="https://brew.sh">Homebrew</a> and surely through other sources as well.</p> <pre><code>$ curl https://download.java.net/java/GA/jdk16.0.1/7147401fd7354114ac51ef3e1328291f/9/GPL/openjdk-16.0.1_osx-x64_bin.tar.gz --output openjdk-16.0.1_osx-x64_bin.tar.gz $ tar xzf openjdk-16.0.1_osx-x64_bin.tar.gz $ sudo port install autoconf $ sh ./configure --with-boot-jdk=$HOME/jdk-16.0.1.jdk/Contents/Home $ make images</code></pre> <p>In this case the built JDK can be found in <code>build/macosx-x86_64-server-release/jdk</code>.</p> <h2 id="configuration-options">Configuration options</h2> <p>The JDK build is extremely configurable. This list only contains the most basic configure options needed to get you started. Use <code>configure --help</code> to see a complete list of options.</p> <table> <colgroup> <col width="50%" /> <col width="50%" /></colgroup> <thead> <tr class="header"> <th align="left">Option</th> <th align="left">What it does</th> </tr> </thead> <tbody> <tr class="odd"> <td align="left"><code>--with-boot-jdk</code></td> <td align="left">Tell configure what boot JDK to use to build the Java libraries.</td> </tr> <tr class="even"> <td align="left"><code>--with-debug-level</code></td> <td align="left">Set the debug level. Available levels are <code>release</code>, <code>fastdebug</code>, <code>slowdebug</code>, <code>optimized</code>.</td> </tr> </tbody> </table> <h3 id="working-with-multiple-configurations">Working with multiple configurations</h3> <p>Through the configure flags you will select what configuration of the JDK to build. The name of the output directory for the build depends on this configuration. In the example above the JDK ended up in <code>linux-x86_64-server-release</code>. This means that we made a release build of a 64 bit linux x86 version of the server JDK. If we change some of these options the output directory will be affected accordingly.</p> <p><code>--with-debug-level</code> is one example of a configure option that will change the output directory name. Sometimes it makes sense to have several different configurations in parallel. For example while debugging some code you might want to have both a debug build and a release build to be able to test it properly. The directory naming scheme makes this very easy. Simply configure and build the JDKs you need and they will end up next to each other in the build directory.</p> <p>In the example above we built a <code>release</code> image. To build a debug image as well we can configure with <code>--with-debug-level=slowdebug</code>. This will give us a JDK where for instance asserts in the JDK source code are enabled. To select which JDK to work with in later calls to <code>make</code> add <code>CONF=<configuration></code>.</p> <pre><code>$ sh ./configure --with-boot-jdk=$HOME/jdk-16/ --with-debug-level=slowdebug $ make CONF=slowdebug images $ ls build/ linux-x86_64-server-release linux-x86_64-server-slowdebug</code></pre> <h2 id="make-targets">Make targets</h2> <p><code>make images</code>, as used in the example above, will build a JDK image which is very close to what you’d get from any JDK provider. There are several other make targets you can use depending on what you’re looking for. The table below contains some commonly used make targets.</p> <table> <colgroup> <col width="36%" /> <col width="63%" /></colgroup> <thead> <tr class="header"> <th align="left">Target</th> <th align="left">What it does</th> </tr> </thead> <tbody> <tr class="odd"> <td align="left"><code>exploded-image</code></td> <td align="left">This is the default make target that you’ll get if you simply invoke <code>make</code>.</td> </tr> <tr class="even"> <td align="left"><code>image</code></td> <td align="left">Builds a complete JDK image. A good target to use if you want to build a JDK for general usage or if you want to test something closer to the shipping product. This can also be a good target to use if doing something which might have a build aspect to it.</td> </tr> <tr class="odd"> <td align="left"><code><name>-image</code></td> <td align="left">Build just the image for any of jdk, test, docs, symbols, etc.</td> </tr> <tr class="even"> <td align="left"><code>reconfigure</code></td> <td align="left">Re-runs the configure script with the same arguments as given the last time.</td> </tr> <tr class="odd"> <td align="left"><code>demos</code></td> <td align="left">Builds the demos which for instance make it easy to test something UI related.</td> </tr> <tr class="even"> <td align="left"><code>docs</code></td> <td align="left">Builds the javadoc. Note that a number of classes in the javadoc API are generated during the build, so <code>make docs</code> might do more than simply invoke <code>javadoc</code>, depending on the state of your build.</td> </tr> <tr class="odd"> <td align="left"><code>java.base</code></td> <td align="left">Builds the base module. You can (re)build any module with <code>make <module></code>.</td> </tr> <tr class="even"> <td align="left"><code>hotspot</code></td> <td align="left">Builds the JVM. Note that the JVM depends on several other parts of the JDK, so <code>make hotspot</code> might build more than just the JVM, depending on the state of your build.</td> </tr> <tr class="odd"> <td align="left"><code>clean</code></td> <td align="left">Removes all files generated by make, but not those generated by configure. Useful when doing significant renaming or refactoring which may confuse the incremental build. To clean out a specific module only use <code>make clean-<module></code>.</td> </tr> <tr class="even"> <td align="left"><code>dist-clean</code></td> <td align="left">Removes all files, including configuration.</td> </tr> </tbody> </table> <p>There are many other targets available as well. Use <code>make help</code> to find out more.</p> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="testing-the-jdk">Testing the JDK</h1> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://openjdk.org/groups/build/doc/testing.html">Using the run-test Framework</a></li> <li><a href="https://openjdk.org/jtreg/">jtreg Harness Documentation</a></li> <li><a href="https://github.com/google/googletest/blob/main/docs/index.md">Google Test Documentation</a></li> </ul> </div> <p>In addition to your own Java applications, OpenJDK has support for two test frameworks to test the JDK, jtreg and GTest. jtreg is a Java regression test framework that is used for most of the tests that are included in the OpenJDK source repository. The Google Test (GTest) framework is intended for unit testing of the C++ native code. Currently only JVM testing is supported by the GTest framework. Other areas use jtreg for unit testing of C++ code.</p> <p>This section provides a brief summary of how to get started with testing in OpenJDK. For more information on configuration and how to use the OpenJDK test framework, a.k.a. “run-test framework”, see <a href="https://github.com/openjdk/jdk/blob/master/doc/testing.md"><code>doc/testing.md</code></a>.</p> <p>Please note that what’s mentioned later in this section, like <a href="#github-actions">GHA</a> and tier 1 testing, will only run a set of smoke-tests to ensure your change compiles and runs on a variety of platforms. They won’t do any targeted testing on the particular code you have changed. You must always make sure your change works as expected before integrating, using targeted testing. In general all changes should come with a regression test, so if you’re writing product code you should also be writing test code. Including the new tests (in the right places) in your change will ensure your tests will be run as part of your testing on all platforms and in the future.</p> <p>A few key items to think about when writing a regression test:</p> <ul> <li>A regression test should execute fast - a few seconds at most</li> <li>The test should only test the desired functionality - if you have several features to test, write more tests</li> <li>The test should pass reliably on all supported platforms - watch out for platform-specific differences such as path separators</li> <li>Binary files shouldn’t be checked in, if your test needs to use one, the test should create it in some fashion</li> <li>Avoid shell scripts and relying on external commands as much as possible</li> </ul> <p>The jtreg documentation has a section on <a href="https://openjdk.org/jtreg/writetests.html">how to write good jtreg tests</a>.</p> <p>There are a few examples where it doesn’t make sense to write an explicit regression test. These should be tagged in JBS with one of the <a href="#noreg">noreg-labels</a>.</p> <h2 id="jtreg">jtreg</h2> <p>In-depth documentation about the jtreg framework is found here: <a href="https://openjdk.org/jtreg/">jtreg harness</a>. jtreg itself is available in the <a href="https://openjdk.org/projects/code-tools/">Code Tools Project</a>.</p> <p>Below is a small example of a jtreg test. It’s a clean Java class with a main method that is called from the test harness. If the test fails we throw a RuntimeException. This is picked up by the harness and is reported as a test failure. Try to always write a meaningful message in the exception. One that actually helps with understanding what went wrong once the test fails.</p> <div class="sourceCode" id="cb10"> <pre class="sourceCode java"><code class="sourceCode java"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="co">/*</span></span> <span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="co"> * @test</span></span> <span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="co"> * @summary Make sure feature X handles Y correctly</span></span> <span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="co"> * @run main TestXY</span></span> <span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="co"> */</span></span> <span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> TestXY <span class="op">{</span></span> <span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a> <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="kw">throws</span> <span class="bu">Exception</span> <span class="op">{</span></span> <span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a> var result <span class="op">=</span> X<span class="op">.</span><span class="fu">y</span><span class="op">();</span></span> <span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="op">(</span>result <span class="op">!=</span> expected_result<span class="op">)</span> <span class="op">{</span></span> <span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a> <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">RuntimeException</span><span class="op">(</span><span class="st">"X.y() gave "</span> <span class="op">+</span> result <span class="op">+</span> <span class="st">", expected "</span> <span class="op">+</span> expected_result<span class="op">);</span></span> <span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span> <span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span> <span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> <p>This example only utilizes three jtreg specific tags, <code>@test</code>, <code>@summary</code>, and <code>@run</code>. <code>@test</code> simply tells jtreg that this class is a test, and <code>@summary</code> provides a description of the test. <code>@run</code> tells jtreg how to execute the test. In this case we simply tell jtreg to execute the main method of the class <code>TestXY</code>. <code>@run</code> isn’t strictly necessary for jtreg to execute the test, an implicit <code>@run</code> tag will be added if none exists. However, for clarity and in order to avoid bugs it’s recommended to always explicitly use the <code>@run</code> tag.</p> <p>There are several other tags that can be used in jtreg tests. You can for instance associate the test with a specific bug that this test is a regression test for. The bug id is written without the <code>JDK-</code> prefix.</p> <pre><code>@bug 8272373</code></pre> <p>You can add several bug ids in the same <code>@bug</code> tag, separated by a single space. These bug ids refer to product bugs for which a fix is verified by this test. JBS issues that track changes to the test itself are not listed here.</p> <p>You can also specify a number of requirements that must be fulfilled for jtreg to execute the test.</p> <pre><code>@requires docker.support @requires os.family != "windows" @requires os.maxMemory > 3G @requires os.arch=="x86_64" | os.arch=="amd64"</code></pre> <p>And you can specify if the test requires specific modules, or command line flags to run the test in several different ways.</p> <pre><code>@modules java.base/jdk.internal.misc @run main/othervm -Xmx128m TestXY</code></pre> <p>Note that you can have several <code>@run</code> tags in the same test with different command line options.</p> <p>jtreg also have support for labeling tests with keys using the <code>@key</code> tag. These keywords can then be used to filter the test selection. For instance if you have a UI test which needs to display a window you’ll want to make sure the test harness doesn’t try to run this test on a system which doesn’t support headful tests. You do this by specifying</p> <pre><code>@key headful</code></pre> <p>Another example is <code>@key randomness</code> that should be used to indicate that a test is using randomness - i.e. is intentionally non-deterministic.</p> <p>There are many other keywords in use and their usage may differ between areas in the JDK. Make sure you understand the conventions for the particular area you are testing since these are just examples.</p> <p>The <a href="https://openjdk.org/jtreg/">jtreg documentation</a> provides information on many more tags like these.</p> <p>The <a href="https://openjdk.org/groups/compiler/">compiler group</a> has a section in their wiki with <a href="https://openjdk.org/groups/compiler/tests.html">Guidelines for “langtools” tests</a>.</p> <h3 id="running-openjdk-jtreg-tests">Running OpenJDK jtreg tests</h3> <p>When configuring the OpenJDK build you can tell it where your jtreg installation is located. When providing this information you can later run <code>make run-test</code> to execute jtreg tests.</p> <pre><code>sh ./configure --with-jtreg=/path/to/jtreg make run-test TEST=tier1</code></pre> <p>In the OpenJDK source tree you can find a directory called <code>test</code>. There are a large number of tests in this directory that are written to be used with jtreg.</p> <pre><code>make run-test TEST=test/jdk/java/lang/String/</code></pre> <p>You can also run jtreg without invoking make. In this case you’ll need to tell jtreg which JDK to test.</p> <pre><code>jtreg -jdk:/path/to/jdk /path/to/test</code></pre> <h2 id="gtest">GTest</h2> <p>As mentioned the Google test framework is mainly used for C++ unit tests. There are several of these in the <code>test/hotspot</code> directory. Currently, only the C++ code in the JVM area is supported by the OpenJDK GTest framework. The tests can be run without starting the JVM, which enables testing of JVM data structures that would be fragile to play with in a running JVM.</p> <div class="sourceCode" id="cb18"> <pre class="sourceCode java"><code class="sourceCode java"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">int</span> <span class="fu">demo_comparator</span><span class="op">(</span><span class="dt">int</span> a<span class="op">,</span> <span class="dt">int</span> b<span class="op">)</span> <span class="op">{</span></span> <span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="op">(</span>a <span class="op">==</span> b<span class="op">)</span> <span class="op">{</span></span> <span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span> <span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span> <span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="op">(</span>a <span class="op"><</span> b<span class="op">)</span> <span class="op">{</span></span> <span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="op">-</span><span class="dv">1</span><span class="op">;</span></span> <span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span> <span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="dv">1</span><span class="op">;</span></span> <span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span> <span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a></span> <span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a><span class="fu">TEST</span><span class="op">(</span>Demo<span class="op">,</span> quicksort<span class="op">)</span> <span class="op">{</span></span> <span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a> <span class="dt">int</span> test_array<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><span class="dv">7</span><span class="op">,</span><span class="dv">1</span><span class="op">,</span><span class="dv">5</span><span class="op">,</span><span class="dv">3</span><span class="op">,</span><span class="dv">6</span><span class="op">,</span><span class="dv">9</span><span class="op">,</span><span class="dv">8</span><span class="op">,</span><span class="dv">2</span><span class="op">,</span><span class="dv">4</span><span class="op">,</span><span class="dv">0</span><span class="op">};</span></span> <span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a> <span class="dt">int</span> expected_array<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><span class="dv">0</span><span class="op">,</span><span class="dv">1</span><span class="op">,</span><span class="dv">2</span><span class="op">,</span><span class="dv">3</span><span class="op">,</span><span class="dv">4</span><span class="op">,</span><span class="dv">5</span><span class="op">,</span><span class="dv">6</span><span class="op">,</span><span class="dv">7</span><span class="op">,</span><span class="dv">8</span><span class="op">,</span><span class="dv">9</span><span class="op">};</span></span> <span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a></span> <span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a> QuickSort<span class="op">::</span><span class="fu">sort</span><span class="op">(</span>test_array<span class="op">,</span> <span class="dv">10</span><span class="op">,</span> demo_comparator<span class="op">,</span> <span class="kw">false</span><span class="op">);</span></span> <span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op"><</span> <span class="dv">10</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span> <span id="cb18-17"><a href="#cb18-17" aria-hidden="true" tabindex="-1"></a> <span class="fu">ASSERT_EQ</span><span class="op">(</span>expected_array<span class="op">[</span>i<span class="op">],</span> test_array<span class="op">[</span>i<span class="op">]);</span></span> <span id="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span> <span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> <p><code>ASSERT_EQ</code> is one example of an assertion that can be used in the test. Below are a few other examples. A full list is found in the <a href="https://github.com/google/googletest/blob/main/docs/index.md">Google Test Documentation</a>.</p> <div class="sourceCode" id="cb19"> <pre class="sourceCode java"><code class="sourceCode java"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="fu">ASSERT_TRUE</span><span class="op">(</span>condition<span class="op">);</span></span> <span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="fu">ASSERT_FALSE</span><span class="op">(</span>condition<span class="op">);</span></span> <span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><span class="fu">EXPECT_EQ</span><span class="op">(</span>expected<span class="op">,</span> actual<span class="op">);</span></span> <span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a><span class="fu">EXPECT_LT</span><span class="op">(</span>val1<span class="op">,</span> val2<span class="op">);</span></span> <span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a><span class="fu">EXPECT_STREQ</span><span class="op">(</span>expected_str<span class="op">,</span> actual_str<span class="op">);</span></span></code></pre></div> <p><code>ASSERT</code> is a fatal assertion and will interrupt execution of the current sub-routine. <code>EXPECT</code> is a nonfatal assertion and will report the error but continues to run the test. All assertions have both an <code>ASSERT</code> and an <code>EXPECT</code> variant.</p> <p>For more information on how to write good GTests in HotSpot, see <a href="https://github.com/openjdk/jdk/blob/master/doc/hotspot-unit-tests.md"> <code>doc/hotspot-unit-tests.md</code></a>.</p> <h3 id="running-openjdk-gtests">Running OpenJDK GTests</h3> <p>When configuring the OpenJDK build you can tell it where your GTest installation is located. Once configured, use make to run GTests.</p> <pre><code>sh ./configure --with-gtest=/path/to/gtest make test TEST=gtest</code></pre> <p>You can also use a regular expression to filter which tests to run:</p> <pre><code>make test TEST=gtest:code.*:os.* make test TEST=gtest:$X/$variant</code></pre> <p>The second example above runs tests which match the regexp <code>$X.*</code> on a specific variant of the JVM. The variant is one of client, server, etc.</p> <h2 id="github-actions">GitHub actions</h2> <p><a href="https://github.com">GitHub</a> has a feature called <strong>GitHub actions</strong> (GHA) that can be used to automate testing. The GHA is executed whenever a push is made to a branch in your repository. The bots will show the results of the GHA in your PR when you create or update it. The GHA in the JDK Project is configured to run a set of tests that is commonly known as <strong>tier 1</strong>. This is a relatively fast, small set of tests that tries to verify that your change didn’t break the JDK completely. In tier 1 the JDK is built on a small set of platforms including (but not necessarily limited to) Linux, Windows, and MacOS, and a few tests are executed using these builds. There’s also a set of other platforms for which GHA does cross-complilation builds.</p> <p>In addition to the testing you run manually before publishing your changes, it’s recommended that you take advantage of this automated testing that the GHA offers. This will for instance allow you to run tests on platforms that you may not otherwise have access to. To enable this on your personal fork of the JDK on <a href="https://github.com">GitHub</a> go to the “Actions” tab and click the big green button saying “I understand my workflows, go ahead and enable them”. If you don’t understand these workflows there’s a link to the actual file that describes them right below the green button.</p> <p>In case of failures in the GHA it’s always a good start to try to reproduce the failure locally on a machine where you have better control and easier access to a debug environment. There have been cases where the GHA has failed due to issues unrelated to the change being tested, e.g. because the GHA environment was updated and changes were needed to the JDK GHA configuration. The configuration is in general updated fairly quickly, so in cases were you can’t reproduce the failure locally, consider re-running the GHA later.</p> <p>Please keep in mind that the tier 1 tests run by the GHA should only be seen as a smoke test that finds the most critical breakages, like build errors or if the JDK is DOA. These tests can never replace the targeted testing that you always must do on your changes. There are several areas of the JDK that aren’t part of tier 1 at all. To see exactly what tier 1 includes, please see the various TEST.groups files that you will find in the subdirectories of <a href="https://github.com/openjdk/jdk/tree/master/test"><code>jdk/test/</code></a>.</p> <div class="note"> <p>In the past there used to be a sandbox repository that could be used for testing purposes. With the move to Git this has been replaced by GitHub Actions.</p> </div> <h2 id="excluding-a-test">Excluding a test</h2> <p>Sometimes tests break. It could be e.g. due to bugs in the test itself, due to changed functionality in the code that the test is testing, or changes in the environment where the test is executed. While working on a fix, it can be useful to stop the test from being executed in everyone else’s testing to reduce noise, especially if the test is expected to fail for more than a day. There are two ways to stop a test from being run in standard test runs: ProblemListing and using the <code>@ignore</code> keyword. Removing tests isn’t the standard way to remove a failure. A failing test is often a regression and should ideally be handled with high urgency.</p> <p>Remember to remove the JBS id from the ProblemList or the test when the bug is closed. This is especially easy to forget if a bug is closed as <span class="jbs-value">Duplicate</span> or <span class="jbs-value">Won’t Fix</span>. jcheck will report an error and prohibit an integration if a PR is created for an issue that is found in a ProblemList if the fix doesn’t remove the bug ID from the ProblemList.</p> <h3 id="problemlisting-jtreg-tests">ProblemListing jtreg tests</h3> <p>ProblemListing should be used for a short term exclusion while a test is being fixed, and for the exclusion of intermittently failing tests that cause too much noise, but can still be useful to run on an ad-hoc basis. ProblemListing is done in the file <code>ProblemList.txt</code>. For more details about the <code>ProblemList.txt</code> file see the <a href="https://openjdk.org/jtreg/faq.html#what-is-a-problemlist.txt-file"> jtreg FAQ</a>.</p> <p>There are actually several ProblemList files to choose from in the JDK. Their location and name hint about what area or feature each file belongs to. Each file has sections for different components. All ProblemList files complement each other to build the total set of tests to exclude in jtreg runs.</p> <pre><code>test/hotspot/jtreg/ProblemList.txt test/hotspot/jtreg/ProblemList-aot.txt test/hotspot/jtreg/ProblemList-graal.txt test/hotspot/jtreg/ProblemList-non-cds-mode.txt test/hotspot/jtreg/ProblemList-Xcomp.txt test/hotspot/jtreg/ProblemList-zgc.txt test/jaxp/ProblemList.txt test/jdk/ProblemList.txt test/jdk/ProblemList-aot.txt test/jdk/ProblemList-graal.txt test/jdk/ProblemList-Xcomp.txt test/langtools/ProblemList.txt test/langtools/ProblemList-graal.txt test/lib-test/ProblemList.txt</code></pre> <p>Use the suitable ProblemList and add a line like this in the proper section:</p> <pre><code>foo/bar/MyTest.java 4711 windows-all</code></pre> <p>In this example, <code>MyTest.java</code> is ProblemListed on windows, tracked by bug <code>JDK-4711</code>.</p> <p>Currently there’s <a href="https://bugs.openjdk.org/browse/CODETOOLS-7902481">no support for multiple lines for the same test</a>. For this reason it’s important to always make sure there’s no existing entry for the test before adding a new one, as multiple entries might lead to unexpected results, e.g.</p> <pre><code>foo/bar/MyTest.java 4710 generic-all ... foo/bar/MyTest.java 4711 windows-all</code></pre> <p>This would lead to <code>sun.tools.jcmd.MyTest.java</code> being ProblemListed only on <code>windows-all</code>. The proper way to write this is:</p> <pre><code>foo/bar/MyTest.java 4710,4711 generic-all,windows-all</code></pre> <p>Although <code>windows-all</code> isn’t strictly required in this example, it’s preferable to specify platforms for each bugid (unless they are all <code>generic-all</code>), this makes it easier to remove one of the bugs from the list.</p> <p>A common way to handle the JBS issue used to problemlist a test is to create a <span class="jbs-value">Sub-task</span> of the bug that needs to be fixed to be able to remove the test from the problem list again.</p> <p>Remember to always add a <span class="jbs-label">problemlist</span> label in the JBS issue referenced in the ProblemList entry.</p> <h4 id="problemlisting-some-but-not-all-test-cases-in-a-file"> ProblemListing some, but not all, test cases in a file</h4> <p>Some tests contain several test cases and there may be a need to ProblemList only a few of them. To do this use the full test name, i.e. <code><filename> + # + <test case id></code>, where test case id can be specified in the test header. If no id is specified each test case can be referenced with <code>id</code> + ordinary number of the test case in the test file.</p> <p>Let’s assume we have four test cases in <code>foo/bar/MyTest.java</code>:</p> <pre><code>/* @test */ /* @test id=fancy_name */ /* @test */ /* @test */</code></pre> <p>A ProblemList entry that excludes the first, second, and third test case would look like this:</p> <pre><code>foo/bar/MyTest.java#id0 4720 generic-all foo/bar/MyTest.java#fancy_name 4721 generic-all foo/bar/MyTest.java#id2 4722 generic-all</code></pre> <p>Due to an issue described in <a href="https://bugs.openjdk.org/browse/CODETOOLS-7902712">CODETOOLS-7902712</a> tests that contains more than one <code>@test</code> must actually use this way to specify all test cases if all of them should be ProblemListed. Specifying just the test name will not work.</p> <h4 id="running-problemlisted-tests">Running ProblemListed tests</h4> <p>To run ad-hoc runs of ProblemListed tests use <code>RUN_PROBLEM_LISTS=true</code>.</p> <pre><code>make test TEST=... JTREG=RUN_PROBLEM_LISTS=true</code></pre> <h3 id="exclude-jtreg-tests-using-ignore">Exclude jtreg tests using <code>@ignore</code></h3> <p>The <code>@ignore</code> keyword is used in the test source code. This is mainly used for tests that are so broken that they may be harmful or useless, and is less common than ProblemListing. Examples can be tests that don’t compile because something changed in the platform; or a test which might remove your <code>/etc/shadow</code>. Use <code>@ignore</code> with a bug reference in the test case to prevent the test from being run.</p> <div class="sourceCode" id="cb29"> <pre class="sourceCode java"><code class="sourceCode java"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="co">/**</span></span> <span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span> <span class="co">@</span>test</span> <span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span> <span class="co">@</span>ignore <span class="co">4711</span></span> <span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a> <span class="co">*/</span></span></code></pre></div> <p>In this example, <code>MyTest.java</code> is excluded, tracked by bug <code>JDK-4711</code>. <code>@ignore</code> should generally be placed directly before the first “action” tag (e.g. <code>@compile</code>, <code>@run</code>) if any in the test.</p> <h3 id="dealing-with-jbs-bugs-for-test-exclusion">Dealing with JBS bugs for test exclusion</h3> <p>ProblemListing and <code>@ignore</code>-ing are done in the JDK source tree, that means a check-in into the repository is needed. This in turn means that a unique JBS issue and a code review are needed. This is a good thing since it makes test problems visible.</p> <ul> <li><strong>Code review</strong>: ProblemListing a test is considered a <a href="#trivial">trivial</a> change.</li> <li><strong>JBS issue</strong>: A JBS issue is obviously created for the bug that caused the failure, we call this the <em>main issue</em>. To exclude the test, create a subtask to the main issue. Also add the label <a href="#problemlist"><span class="jbs-label">problemlist</span></a> to the main issue.</li> </ul> <p>The fix for the main issue should remove the test from the ProblemList or remove the <code>@ignore</code> keyword from the test.</p> <h4 id="triage-excluded-issues">Triage excluded issues</h4> <p>After a failure is handled by excluding a test, the main JBS issue should be re-triaged and possibly given a new priority. This should be handled by the standard triage process. A test exclusion results in an outage in our testing. This outage should be taken into consideration when triaging, in addition to the impact of the bug itself.</p> <h2 id="backing-out-a-change">Backing out a change</h2> <p>If a change causes a regression that can’t be fixed within reasonable time, the best way to handle the regression can be to back out the change. Backing out means that the inverse (anti-delta) of the change is integrated to effectively undo the change in the repository. Whether to back out a change or not will always be a judgement call. How noisy and frequent are the failures caused by the broken change? How soon can the fix be expected? If you want to avoid having your change backed out, you should make sure to let the relevant developers know that you are working on the fix and give an estimated ETA of the fix.</p> <p>It will happen of course when the build is broken or the JDK is DOA and similar situations that a change is immediately backed out without further investigation. Backing out a change is however seldom the first course of action if the change has been done in accordance with the guidance in <a href="#working-with-pull-requests">Working With Pull Requests</a>. If, when investigated, it is found that a change didn’t go through relevant testing or there are other issues that should have been caught before integration if proper procedure had been followed, it’s quite possible that a change is backed out even if the author is desperately working on a fix. The JDK source code is deliberately menat to have a high bar for acceptance of changes. If something crawls in underneath that bar it should most likely be backed out.</p> <p>The backout is a regular change and will have to go through the standard code review process, but is considered a <a href="#trivial">trivial</a> change. The rationale is that a backout is usually urgent in nature and the change itself is automatically generated. In areas where two reviewers are normally required, only one <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a> is required for a backout since the person who is performing the backout also should review the change.</p> <p>There are two parts to this task, how to do the bookkeeping in JBS, and how to do the actual backout in git.</p> <h3 id="how-to-work-with-jbs-when-a-change-is-backed-out">How to work with JBS when a change is backed out</h3> <ol> <li>Close the original (failed) JBS issue <strong>(O)</strong>. <ul> <li>“Verify” the issue and choose “Fix Failed”.</li> </ul> </li> <li>If the intention is to fix the change and submit it again, create a redo-issue <strong>(R)</strong> to track that the work still needs to be done. <ul> <li>Clone <strong>(O)</strong> and add the prefix <code>[REDO]</code> on the summary - the clone becomes the redo-issue <strong>(R)</strong>.</li> <li>Make sure relevant information is brought to <strong>(R)</strong>.</li> <li>Remember that comments aren’t automatically brought over when cloning.</li> </ul> </li> <li>Create a backout-issue <strong>(B)</strong>: <ul> <li>Alternative 1 - the regression is identified directly. <ul> <li>Create a sub-task to <strong>(R)</strong> with the same summary prefixed with <code>[BACKOUT]</code>.</li> </ul> </li> <li>Alternative 2 - an investigation issue was created <strong>(I)</strong>, and during the investigation backing out the change is identified as the best solution. <ul> <li>Use the investigation issue <strong>(I)</strong> for the backout.</li> <li>Change summary of <strong>(I)</strong> to the same as <strong>(O)</strong> and prefix with <code>[BACKOUT]</code>.</li> <li>Move and change type of <strong>(I)</strong> to become a sub-task of <strong>(R)</strong>.</li> </ul> </li> <li>Alternative 3 - no redo issue was created. <ul> <li>Create a backout-issue <strong>(B)</strong> with the same summary as <strong>(O)</strong>, prefix with <code>[BACKOUT]</code>.</li> <li>Add a <em>relates to</em> link between <strong>(B)</strong> and <strong>(O)</strong>.</li> </ul> </li> </ul> </li> </ol> <p>ProblemList entries and <code>@ignore</code> keywords will continue to point to the original bug (unless updated at back out). This is accepted since there is a clone link to follow.</p> <h3 id="how-to-work-with-git-when-a-change-is-backed-out">How to work with git when a change is backed out</h3> <p>To backout a change with git, use <code>git revert</code>. This will apply (commit) the anti-delta of the change.</p> <div class="sourceCode" id="cb30"> <pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a>$ git show aa371b4f02c2f809eb9cd3e52aa12b639bed1ef5</span> <span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>commit aa371b4f02c2f809eb9cd3e52aa12b639bed1ef5 (HEAD -> master)</span> <span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>Author: Jesper Wilhelmsson <jesper.wilhelmsson@oracle.com></span> <span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>Date: Wed Jun 23 20:31:32 2021 +0200</span> <span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a></span> <span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a> 8272373: Make the JDK mine</span> <span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a> Reviewed-by: duke</span> <span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a></span> <span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a><span class="kw">diff --git a/README.md b/README.md</span></span> <span id="cb30-10"><a href="#cb30-10" aria-hidden="true" tabindex="-1"></a>index 399e7cc311f..4961acb2126 100644</span> <span id="cb30-11"><a href="#cb30-11" aria-hidden="true" tabindex="-1"></a><span class="dt">--- a/README.md</span></span> <span id="cb30-12"><a href="#cb30-12" aria-hidden="true" tabindex="-1"></a><span class="dt">+++ b/README.md</span></span> <span id="cb30-13"><a href="#cb30-13" aria-hidden="true" tabindex="-1"></a><span class="dt">@@ -1,4 +1,4 @@</span></span> <span id="cb30-14"><a href="#cb30-14" aria-hidden="true" tabindex="-1"></a><span class="st">-# Welcome to the JDK!</span></span> <span id="cb30-15"><a href="#cb30-15" aria-hidden="true" tabindex="-1"></a><span class="va">+# Welcome to my modified JDK!</span></span> <span id="cb30-16"><a href="#cb30-16" aria-hidden="true" tabindex="-1"></a></span> <span id="cb30-17"><a href="#cb30-17" aria-hidden="true" tabindex="-1"></a> For build instructions please see the</span> <span id="cb30-18"><a href="#cb30-18" aria-hidden="true" tabindex="-1"></a> [online documentation](https://openjdk.org/groups/build/doc/building.html),</span> <span id="cb30-19"><a href="#cb30-19" aria-hidden="true" tabindex="-1"></a></span> <span id="cb30-20"><a href="#cb30-20" aria-hidden="true" tabindex="-1"></a>$ git revert aa371b4f02c2f809eb9cd3e52aa12b639bed1ef5</span> <span id="cb30-21"><a href="#cb30-21" aria-hidden="true" tabindex="-1"></a>[master d454489052d] 8280996: [BACKOUT] Make the JDK mine Reviewed-by: duke</span> <span id="cb30-22"><a href="#cb30-22" aria-hidden="true" tabindex="-1"></a> 1 file changed, 1 insertion(+), 1 deletion(-)</span> <span id="cb30-23"><a href="#cb30-23" aria-hidden="true" tabindex="-1"></a></span> <span id="cb30-24"><a href="#cb30-24" aria-hidden="true" tabindex="-1"></a>$ git show d454489052dc6ff69a21ad9c8f56b67fdeb435ee</span> <span id="cb30-25"><a href="#cb30-25" aria-hidden="true" tabindex="-1"></a>commit d454489052dc6ff69a21ad9c8f56b67fdeb435ee (HEAD -> master)</span> <span id="cb30-26"><a href="#cb30-26" aria-hidden="true" tabindex="-1"></a>Author: Jesper Wilhelmsson <jesper.wilhelmsson@oracle.com></span> <span id="cb30-27"><a href="#cb30-27" aria-hidden="true" tabindex="-1"></a>Date: Wed Jun 23 20:32:08 2021 +0200</span> <span id="cb30-28"><a href="#cb30-28" aria-hidden="true" tabindex="-1"></a></span> <span id="cb30-29"><a href="#cb30-29" aria-hidden="true" tabindex="-1"></a> 8280996: [BACKOUT] Make the JDK mine</span> <span id="cb30-30"><a href="#cb30-30" aria-hidden="true" tabindex="-1"></a> Reviewed-by: duke</span> <span id="cb30-31"><a href="#cb30-31" aria-hidden="true" tabindex="-1"></a></span> <span id="cb30-32"><a href="#cb30-32" aria-hidden="true" tabindex="-1"></a><span class="kw">diff --git a/README.md b/README.md</span></span> <span id="cb30-33"><a href="#cb30-33" aria-hidden="true" tabindex="-1"></a>index 4961acb2126..399e7cc311f 100644</span> <span id="cb30-34"><a href="#cb30-34" aria-hidden="true" tabindex="-1"></a><span class="dt">--- a/README.md</span></span> <span id="cb30-35"><a href="#cb30-35" aria-hidden="true" tabindex="-1"></a><span class="dt">+++ b/README.md</span></span> <span id="cb30-36"><a href="#cb30-36" aria-hidden="true" tabindex="-1"></a><span class="dt">@@ -1,4 +1,4 @@</span></span> <span id="cb30-37"><a href="#cb30-37" aria-hidden="true" tabindex="-1"></a><span class="st">-# Welcome to my modified JDK!</span></span> <span id="cb30-38"><a href="#cb30-38" aria-hidden="true" tabindex="-1"></a><span class="va">+# Welcome to the JDK!</span></span> <span id="cb30-39"><a href="#cb30-39" aria-hidden="true" tabindex="-1"></a></span> <span id="cb30-40"><a href="#cb30-40" aria-hidden="true" tabindex="-1"></a> For build instructions please see the</span> <span id="cb30-41"><a href="#cb30-41" aria-hidden="true" tabindex="-1"></a> [online documentation](https://openjdk.org/groups/build/doc/building.html),</span></code></pre></div> <h2 id="backing-out-a-backport">Backing out a backport</h2> <p>In rare cases it may be necessary to back out a backport from an update release without backing out the original fix in mainline. This will require a somewhat different procedure and will result in a small mess in JBS. It’s extremely important to add comments in all relevant issues explaining exactly what’s happened.</p> <p>The steps to take in order to do this are described below. <strong>(M)</strong> used below refers to the main bug entry - the first fix that was later backported.</p> <ol> <li>Close the original (failed) JBS backport issue <strong>(O)</strong>. <ul> <li>“Verify” the issue and choose “Fix Failed”.</li> </ul> </li> <li>If the intention is to fix the backport and submit it again, create a redo-issue <strong>(R)</strong> to track that the work still needs to be done. <ul> <li>Clone <strong>(M)</strong> and add the prefix <code>[REDO BACKPORT]</code> on the summary - the clone becomes the redo-issue <strong>(R)</strong>.</li> <li>Add a <em>relates to</em> link between <strong>(R)</strong> and <strong>(O)</strong>.</li> <li>Set Fix Version of <strong>(R)</strong> to the target release for the backport - either the exact release if known, or <code><N>-pool</code> if it’s not critical which release the fixed backport goes into.</li> </ul> </li> <li>Create a backout-issue <strong>(B)</strong>: <ul> <li>Alternative 1 - the broken backport is identified directly. <ul> <li>Create a sub-task to <strong>(R)</strong> with the same summary, but prefixed with <code>[BACKOUT BACKPORT]</code>.</li> </ul> </li> <li>Alternative 2 - an investigation issue was created <strong>(I)</strong>, and during the investigation backing out the backport is identified as the best solution. <ul> <li>Use the investigation issue <strong>(I)</strong> for the backout.</li> <li>Change summary of <strong>(I)</strong> to the same as <strong>(M)</strong> and prefix with <code>[BACKOUT BACKPORT]</code>.</li> <li>Move and change type of <strong>(I)</strong> to become a sub-task of <strong>(R)</strong>.</li> </ul> </li> <li>Alternative 3 - no redo issue was created. <ul> <li>Create a backout-issue <strong>(B)</strong> with the same summary as <strong>(M)</strong> and prefix with <code>[BACKOUT BACKPORT]</code>.</li> <li>Add a <em>relates to</em> link between <strong>(B)</strong> and <strong>(M)</strong>.</li> </ul> </li> </ul> </li> <li>Add comments to <strong>(M)</strong>, <strong>(R)</strong> and <strong>(O)</strong> explaining the situation.</li> </ol> <p>The end result in JBS should look like this:</p> <div style="text-align:center;"> <div class="figure"><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibWVybWFpZC0xNzM4MTkwNjU2MDExIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgaGVpZ2h0PSI1OTYiIHN0eWxlPSJtYXgtd2lkdGg6IDQzNC45MDRweDsgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7IiB2aWV3Qm94PSIwIDAgNDM0LjkwNDI5Njg3NSA1OTYiPjxzdHlsZT4jbWVybWFpZC0xNzM4MTkwNjU2MDExIHtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7ZmlsbDojMDAwMDAwO30jbWVybWFpZC0xNzM4MTkwNjU2MDExIC5lcnJvci1pY29ue2ZpbGw6IzU1MjIyMjt9I21lcm1haWQtMTczODE5MDY1NjAxMSAuZXJyb3ItdGV4dHtmaWxsOiM1NTIyMjI7c3Ryb2tlOiM1NTIyMjI7fSNtZXJtYWlkLTE3MzgxOTA2NTYwMTEgLmVkZ2UtdGhpY2tuZXNzLW5vcm1hbHtzdHJva2Utd2lkdGg6MnB4O30jbWVybWFpZC0xNzM4MTkwNjU2MDExIC5lZGdlLXRoaWNrbmVzcy10aGlja3tzdHJva2Utd2lkdGg6My41cHg7fSNtZXJtYWlkLTE3MzgxOTA2NTYwMTEgLmVkZ2UtcGF0dGVybi1zb2xpZHtzdHJva2UtZGFzaGFycmF5OjA7fSNtZXJtYWlkLTE3MzgxOTA2NTYwMTEgLmVkZ2UtcGF0dGVybi1kYXNoZWR7c3Ryb2tlLWRhc2hhcnJheTozO30jbWVybWFpZC0xNzM4MTkwNjU2MDExIC5lZGdlLXBhdHRlcm4tZG90dGVke3N0cm9rZS1kYXNoYXJyYXk6Mjt9I21lcm1haWQtMTczODE5MDY1NjAxMSAubWFya2Vye2ZpbGw6IzY2NjtzdHJva2U6IzY2Njt9I21lcm1haWQtMTczODE5MDY1NjAxMSAubWFya2VyLmNyb3Nze3N0cm9rZTojNjY2O30jbWVybWFpZC0xNzM4MTkwNjU2MDExIHN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7fSNtZXJtYWlkLTE3MzgxOTA2NTYwMTEgLmxhYmVse2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtjb2xvcjojMDAwMDAwO30jbWVybWFpZC0xNzM4MTkwNjU2MDExIC5jbHVzdGVyLWxhYmVsIHRleHR7ZmlsbDojMzMzO30jbWVybWFpZC0xNzM4MTkwNjU2MDExIC5jbHVzdGVyLWxhYmVsIHNwYW57Y29sb3I6IzMzMzt9I21lcm1haWQtMTczODE5MDY1NjAxMSAubGFiZWwgdGV4dCwjbWVybWFpZC0xNzM4MTkwNjU2MDExIHNwYW57ZmlsbDojMDAwMDAwO2NvbG9yOiMwMDAwMDA7fSNtZXJtYWlkLTE3MzgxOTA2NTYwMTEgLm5vZGUgcmVjdCwjbWVybWFpZC0xNzM4MTkwNjU2MDExIC5ub2RlIGNpcmNsZSwjbWVybWFpZC0xNzM4MTkwNjU2MDExIC5ub2RlIGVsbGlwc2UsI21lcm1haWQtMTczODE5MDY1NjAxMSAubm9kZSBwb2x5Z29uLCNtZXJtYWlkLTE3MzgxOTA2NTYwMTEgLm5vZGUgcGF0aHtmaWxsOiNlZWU7c3Ryb2tlOiM5OTk7c3Ryb2tlLXdpZHRoOjFweDt9I21lcm1haWQtMTczODE5MDY1NjAxMSAubm9kZSAubGFiZWx7dGV4dC1hbGlnbjpjZW50ZXI7fSNtZXJtYWlkLTE3MzgxOTA2NTYwMTEgLm5vZGUuY2xpY2thYmxle2N1cnNvcjpwb2ludGVyO30jbWVybWFpZC0xNzM4MTkwNjU2MDExIC5hcnJvd2hlYWRQYXRoe2ZpbGw6IzMzMzMzMzt9I21lcm1haWQtMTczODE5MDY1NjAxMSAuZWRnZVBhdGggLnBhdGh7c3Ryb2tlOiM2NjY7c3Ryb2tlLXdpZHRoOjIuMHB4O30jbWVybWFpZC0xNzM4MTkwNjU2MDExIC5mbG93Y2hhcnQtbGlua3tzdHJva2U6IzY2NjtmaWxsOm5vbmU7fSNtZXJtYWlkLTE3MzgxOTA2NTYwMTEgLmVkZ2VMYWJlbHtiYWNrZ3JvdW5kLWNvbG9yOndoaXRlO3RleHQtYWxpZ246Y2VudGVyO30jbWVybWFpZC0xNzM4MTkwNjU2MDExIC5lZGdlTGFiZWwgcmVjdHtvcGFjaXR5OjAuNTtiYWNrZ3JvdW5kLWNvbG9yOndoaXRlO2ZpbGw6d2hpdGU7fSNtZXJtYWlkLTE3MzgxOTA2NTYwMTEgLmNsdXN0ZXIgcmVjdHtmaWxsOmhzbCgwLCAwJSwgOTguOTIxNTY4NjI3NSUpO3N0cm9rZTojNzA3MDcwO3N0cm9rZS13aWR0aDoxcHg7fSNtZXJtYWlkLTE3MzgxOTA2NTYwMTEgLmNsdXN0ZXIgdGV4dHtmaWxsOiMzMzM7fSNtZXJtYWlkLTE3MzgxOTA2NTYwMTEgLmNsdXN0ZXIgc3Bhbntjb2xvcjojMzMzO30jbWVybWFpZC0xNzM4MTkwNjU2MDExIGRpdi5tZXJtYWlkVG9vbHRpcHtwb3NpdGlvbjphYnNvbHV0ZTt0ZXh0LWFsaWduOmNlbnRlcjttYXgtd2lkdGg6MjAwcHg7cGFkZGluZzoycHg7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxMnB4O2JhY2tncm91bmQ6aHNsKC0xNjAsIDAlLCA5My4zMzMzMzMzMzMzJSk7Ym9yZGVyOjFweCBzb2xpZCAjNzA3MDcwO2JvcmRlci1yYWRpdXM6MnB4O3BvaW50ZXItZXZlbnRzOm5vbmU7ei1pbmRleDoxMDA7fSNtZXJtYWlkLTE3MzgxOTA2NTYwMTEgOnJvb3R7LS1tZXJtYWlkLWZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjt9PC9zdHlsZT48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PG1hcmtlciBpZD0iZmxvd2NoYXJ0LXBvaW50RW5kIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI5IiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgMCBMIDEwIDUgTCAwIDEwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ij48L3BhdGg+PC9tYXJrZXI+PG1hcmtlciBpZD0iZmxvd2NoYXJ0LXBvaW50U3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjAiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCA1IEwgMTAgMTAgTCAxMCAwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ij48L3BhdGg+PC9tYXJrZXI+PG1hcmtlciBpZD0iZmxvd2NoYXJ0LWNpcmNsZUVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iMTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyI+PC9jaXJjbGU+PC9tYXJrZXI+PG1hcmtlciBpZD0iZmxvd2NoYXJ0LWNpcmNsZVN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSItMSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ij48L2NpcmNsZT48L21hcmtlcj48bWFya2VyIGlkPSJmbG93Y2hhcnQtY3Jvc3NFbmQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9IjEyIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ij48L3BhdGg+PC9tYXJrZXI+PG1hcmtlciBpZD0iZmxvd2NoYXJ0LWNyb3NzU3RhcnQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9Ii0xIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ij48L3BhdGg+PC9tYXJrZXI+PGcgY2xhc3M9InJvb3QiPjxnIGNsYXNzPSJjbHVzdGVycyI+PC9nPjxnIGNsYXNzPSJlZGdlUGF0aHMiPjxwYXRoIGQ9Ik0xNzAuNTYwMzczMjYzODg4OSw5N0wxNjQuMDA2NjkxMjYxNTc0MDgsMTAyLjcwODMzMzMzMzMzMzMzQzE1Ny40NTMwMDkyNTkyNTkyNiwxMDguNDE2NjY2NjY2NjY2NjcsMTQ0LjM0NTY0NTI1NDYyOTYzLDExOS44MzMzMzMzMzMzMzMzMywxMzcuNzkxOTYzMjUyMzE0ODIsMTMxLjI1QzEzMS4yMzgyODEyNSwxNDIuNjY2NjY2NjY2NjY2NjYsMTMxLjIzODI4MTI1LDE1NC4wODMzMzMzMzMzMzMzNCwxMzEuMjM4MjgxMjUsMTU5Ljc5MTY2NjY2NjY2NjY2TDEzMS4yMzgyODEyNSwxNjUuNSIgaWQ9IkwtbWFpbi1iYWNrcG9ydC0wIiBjbGFzcz0iIGVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtbWFpbiBMRS1iYWNrcG9ydCIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjZmxvd2NoYXJ0LXBvaW50RW5kKSI+PC9wYXRoPjxwYXRoIGQ9Ik0yNzIuNzQwNDA3OTg2MTExMSwzNDEuNUwyNzkuMjk0MDg5OTg4NDI1OSwzMzUuNzkxNjY2NjY2NjY2N0MyODUuODQ3NzcxOTkwNzQwNzQsMzMwLjA4MzMzMzMzMzMzMzMsMjk4Ljk1NTEzNTk5NTM3MDM3LDMxOC42NjY2NjY2NjY2NjY3LDMwNS41MDg4MTc5OTc2ODUyLDI5OC4yOTE2NjY2NjY2NjY3QzMxMi4wNjI1LDI3Ny45MTY2NjY2NjY2NjY3LDMxMi4wNjI1LDI0OC41ODMzMzMzMzMzMzMzNCwzMTIuMDYyNSwyMTkuMjVDMzEyLjA2MjUsMTg5LjkxNjY2NjY2NjY2NjY2LDMxMi4wNjI1LDE2MC41ODMzMzMzMzMzMzMzNCwzMDUuNTA4ODE3OTk3Njg1MiwxNDAuMjA4MzMzMzMzMzMzMzRDMjk4Ljk1NTEzNTk5NTM3MDM3LDExOS44MzMzMzMzMzMzMzMzMywyODUuODQ3NzcxOTkwNzQwNzQsMTA4LjQxNjY2NjY2NjY2NjY3LDI3OS4yOTQwODk5ODg0MjU5LDEwMi43MDgzMzMzMzMzMzMzM0wyNzIuNzQwNDA3OTg2MTExMSw5NyIgaWQ9IkwtcmVkby1tYWluLTAiIGNsYXNzPSIgZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1yZWRvIExFLW1haW4iIHN0eWxlPSJmaWxsOm5vbmU7IiBtYXJrZXItZW5kPSJ1cmwoI2Zsb3djaGFydC1wb2ludEVuZCkiPjwvcGF0aD48cGF0aCBkPSJNMTMxLjIzODI4MTI1LDI3M0wxMzEuMjM4MjgxMjUsMjc4LjcwODMzMzMzMzMzMzNDMTMxLjIzODI4MTI1LDI4NC40MTY2NjY2NjY2NjY3LDEzMS4yMzgyODEyNSwyOTUuODMzMzMzMzMzMzMzMywxMzcuNzkxOTYzMjUyMzE0ODIsMzA3LjI1QzE0NC4zNDU2NDUyNTQ2Mjk2MywzMTguNjY2NjY2NjY2NjY2NywxNTcuNDUzMDA5MjU5MjU5MjYsMzMwLjA4MzMzMzMzMzMzMzMsMTY0LjAwNjY5MTI2MTU3NDA4LDMzNS43OTE2NjY2NjY2NjY3TDE3MC41NjAzNzMyNjM4ODg5LDM0MS41IiBpZD0iTC1iYWNrcG9ydC1yZWRvLTAiIGNsYXNzPSIgZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1iYWNrcG9ydCBMRS1yZWRvIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLXN0YXJ0PSJ1cmwoI2Zsb3djaGFydC1wb2ludFN0YXJ0KSIgbWFya2VyLWVuZD0idXJsKCNmbG93Y2hhcnQtcG9pbnRFbmQpIj48L3BhdGg+PHBhdGggZD0iTTIyMS42NTAzOTA2MjUsNDMwLjVMMjIxLjY1MDM5MDYyNSw0MzYuMjA4MzMzMzMzMzMzM0MyMjEuNjUwMzkwNjI1LDQ0MS45MTY2NjY2NjY2NjY3LDIyMS42NTAzOTA2MjUsNDUzLjMzMzMzMzMzMzMzMzMsMjIxLjY1MDM5MDYyNSw0NjQuNzVDMjIxLjY1MDM5MDYyNSw0NzYuMTY2NjY2NjY2NjY2NywyMjEuNjUwMzkwNjI1LDQ4Ny41ODMzMzMzMzMzMzMzLDIyMS42NTAzOTA2MjUsNDkzLjI5MTY2NjY2NjY2NjdMMjIxLjY1MDM5MDYyNSw0OTkiIGlkPSJMLXJlZG8tYmFja291dC0wIiBjbGFzcz0iIGVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtcmVkbyBMRS1iYWNrb3V0IiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNmbG93Y2hhcnQtcG9pbnRFbmQpIj48L3BhdGg+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWxzIj48ZyBjbGFzcz0iZWRnZUxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMzEuMjM4MjgxMjUsIDEzMS4yNSkiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTUxLjMyMDMxMjUsIC05LjI1KSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjEwMi42NDA2MjUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPmJhY2twb3J0ZWQgYnk8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzEyLjA2MjUsIDIxOS4yNSkiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTIyLjU4NTkzNzUsIC05LjI1KSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjQ1LjE3MTg3NSIgaGVpZ2h0PSIxOC41Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+Y2xvbmVzPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEzMS4yMzgyODEyNSwgMzA3LjI1KSI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMzQuNjgzNTkzNzUsIC05LjI1KSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjY5LjM2NzE4NzUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPnJlbGF0ZXMgdG88L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjIxLjY1MDM5MDYyNSwgNDY0Ljc1KSI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMjkuNjUyMzQzNzUsIC05LjI1KSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjU5LjMwNDY4NzUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPnN1Yi10YXNrPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZXMiPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCIgaWQ9ImZsb3djaGFydC1tYWluLTEyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyMjEuNjUwMzkwNjI1LCA1Mi41KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjUiIHJ5PSI1IiB4PSItMTIzLjIzODI4MTI1IiB5PSItNDQuNSIgd2lkdGg9IjI0Ni40NzY1NjI1IiBoZWlnaHQ9Ijg5Ij48L3JlY3Q+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTE1LjczODI4MTI1LCAtMzcpIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMjMxLjQ3NjU2MjUiIGhlaWdodD0iNzQiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5NYWluIGlzc3VlIDxiPihNKTwvYj48YnIvPkpESy04MjcyMzczOiBFeGFtcGxlIEpCUyBJc3N1ZTxici8+SXNzdWUgdHlwZTogQnVnPGJyLz5GaXggdmVyc2lvbjogMTg8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IiBpZD0iZmxvd2NoYXJ0LWJhY2twb3J0LTEzIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMzEuMjM4MjgxMjUsIDIxOS4yNSkiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSI1IiByeT0iNSIgeD0iLTEyMy4yMzgyODEyNSIgeT0iLTUzLjc1IiB3aWR0aD0iMjQ2LjQ3NjU2MjUiIGhlaWdodD0iMTA3LjUiPjwvcmVjdD48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xMTUuNzM4MjgxMjUsIC00Ni4yNSkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIyMzEuNDc2NTYyNSIgaGVpZ2h0PSI5Mi41Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+SW5pdGlhbCBiYWNrcG9ydCA8Yj4oTyk8L2I+PGJyLz5KREstODI4MDk4NjogRXhhbXBsZSBKQlMgSXNzdWU8YnIvPklzc3VlIHR5cGU6IEJhY2twb3J0PGJyLz5GaXggdmVyc2lvbjogMTUuMC4yPGJyLz5WZXJpZmljYXRpb246IEZpeCBmYWlsZWQ8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IiBpZD0iZmxvd2NoYXJ0LWJhY2tvdXQtMTQiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIyMS42NTAzOTA2MjUsIDU0My41KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjUiIHJ5PSI1IiB4PSItMjA1LjI1MzkwNjI1IiB5PSItNDQuNSIgd2lkdGg9IjQxMC41MDc4MTI1IiBoZWlnaHQ9Ijg5Ij48L3JlY3Q+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTk3Ljc1MzkwNjI1LCAtMzcpIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMzk1LjUwNzgxMjUiIGhlaWdodD0iNzQiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5CYWNrb3V0IG9mIEpESy04MjgwOTg2IDxiPihCKTwvYj48YnIvPkpESy04MjgwOTk2OiBbQkFDS09VVCBCQUNLUE9SVF0gRXhhbXBsZSBKQlMgSXNzdWU8YnIvPklzc3VlIHR5cGU6IFN1Yi10YXNrPGJyLz5GaXggdmVyc2lvbjogMTUuMC4yPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCIgaWQ9ImZsb3djaGFydC1yZWRvLTE1IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyMjEuNjUwMzkwNjI1LCAzODYpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iNSIgcnk9IjUiIHg9Ii0xOTAuNjMyODEyNSIgeT0iLTQ0LjUiIHdpZHRoPSIzODEuMjY1NjI1IiBoZWlnaHQ9Ijg5Ij48L3JlY3Q+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTgzLjEzMjgxMjUsIC0zNykiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIzNjYuMjY1NjI1IiBoZWlnaHQ9Ijc0Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+UmVkbyBvZiBiYWNrcG9ydCA8Yj4oUik8L2I+PGJyLz5KREstODI4MDk4OTogW1JFRE8gQkFDS1BPUlRdIEV4YW1wbGUgSkJTIElzc3VlPGJyLz5Jc3N1ZSB0eXBlOiBCdWc8YnIvPkZpeCB2ZXJzaW9uOiAxNS4wLjI8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" alt="" /> <p class="caption">JBS structure after backout and redo of a backport</p> </div> </div> <p>For this example in JBS see the 15.0.2 backport of <a href="https://bugs.openjdk.org/browse/JDK-8272373">JDK-8272373</a>.</p> <h3 id="rationale-for-using-this-model">Rationale for using this model</h3> <p>The approach described here has both advantages and disadvantages. The key invariants that lead to this model are:</p> <ul> <li>A <em>backported by</em> link should only refer to issues of type Backport</li> <li>A bug id should never be reused for different patches in the same repository</li> </ul> <p>Disadvantages of this model are that the list of backports in JBS will still list the old (failed) backport as the 15.0.2 backport, and the new backport will not be linked to using a <em>backported by</em> link. It is assumed that the advantages above outweighs the disadvantages and that the capital letter prefixes for the backout and the redo will be visible enough in JBS to alert that something fishy is going on.</p> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="working-with-pull-requests">Working With Pull Requests</h1> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://wiki.openjdk.org/display/SKARA/Pull+Request+Commands">Skara documentation on PR commands</a></li> </ul> </div> <p>Once you have made a change that you want to integrate into an OpenJDK code base you need to create a <em>Pull Request</em> (PR) on <a href="https://github.com">GitHub</a>. This section assumes that you have previous experience from using git and <a href="https://github.com">GitHub</a>, and won’t go into details of how those work. Still, the aim is of course to provide a useful guide, so <a href="#about-this-guide">send an email</a> if more details are needed.</p> <p>This section also assumes that you have already read <a href="#i-have-a-patch-what-do-i-do">I have a patch, what do I do?</a> and followed <strong>all</strong> the steps there.</p> <div class="note"> <p>Please note that the description of a change should always be in the JBS issue. The <a href="https://github.com">GitHub</a> PR can be a good place to discuss technical implementation details regarding your change, but it’s not the right place to describe the problem. Make sure you have a proper problem description in your JBS issue before publishing a PR.</p> </div> <h2 id="think-once-more">Think once more</h2> <p>All code reviews in OpenJDK are done in public. Once you open your PR for public review the internet can see it and comment on it. Make sure your code is ready for it. Look through your comments, make sure that temporary code is gone, and make sure you have sanitized your method and variable names. Also, make sure you understand your code. Why is it working? What are the potential pitfalls? What are the edge-cases? If you haven’t already answered all these questions in the mail conversation that preceded this PR, it’s likely that you will need to answer them during the review.</p> <p>It’s also worth taking the extra time to see if the change can be split into a few different separate changes. A large change will take more effort and thus attract fewer <a href="https://openjdk.org/bylaws#reviewer">Reviewers</a>. Smaller changes will get reviewed faster and get better quality reviews. You can compare proposing a single large change to proposing ten individual small unrelated changes. What happens in practice when all these ten changes are presented as one PR is that there’s a focus on say 5-6 of these smaller changes and no one really looks hard at the other 4-5. For complexity, even small changes that are hard to understand and test may be risky.</p> <p>The timing of your change will also affect the availability of reviewers. The JDK runs on a <a href="#release-cycle">six-months release cadence</a>. During the months around the start of the ramp down phase most area experts will be busy working on their own changes and reviewing major features that are planned for the release. If you propose a change during this period (basically May-June, or November-December) it may take a long time before you get the required reviews.</p> <h2 id="rebase-before-creating-the-pr">Rebase before creating the PR</h2> <p>It’s likely that other people have integrated changes to the code base since you created your branch. Make sure to pull the latest changes and rebase your fix on top of that before creating your PR. This is a courtesy issue. Your reviewers shouldn’t have to read your patch on top of old code that has since changed. This is hopefully obvious in cases where the upstream code has gone through cleanups or refactorings, and your patch may need similar cleanups in order to even compile. But even in cases where only smaller changes have been done, the reviewers shouldn’t have to react to issues like “that line of code was moved last week, why is it back there?”.</p> <p>Most changes are made to the <code>master</code> branch of the mainline repository. In these cases, rebase using:</p> <pre><code>git rebase master</code></pre> <p>Note that if you are working on a backport to a stabilization branch you should replace <code>master</code> above with the name of the branch you are targeting. This would be the same name as when you cloned the branch.</p> <p>After the PR has been published, rebasing, force-pushing, and similar actions are strongly discouraged. Such actions will disrupt the workflow for reviewers who fetch the PR branch. Pushing new changes is fine (and even merging if necessary) for a PR under review. Incremental diffs and other tools will help your reviewers see what you have changed. In the end, all commits will be squashed into a single commit automatically, so there’re actually no drawbacks whatsoever to making commits to a PR branch during review.</p> <h2 id="final-check-before-creating-the-pr">Final check before creating the PR</h2> <p>Creating the PR is essentially the same as asking a large group of people to start reviewing your change. Before doing that, you want to make sure your change is done in every detail you have the power to control. These are a few of the things you should think about in order to avoid wasting people’s time on an unfinished change. (You may think that some of these are too obvious to even mention, but all of them are things that in the past have caused actual failures that broke the JDK for <strong>all</strong> developers out there.)</p> <ul> <li> <p>Is the copyright statement at the top of each modified source file correct?</p> </li> <li> <p>Did you run a full build and all relevant tests on the <strong>final</strong> version of the change? It’s important to do this on the truly final version, as even an apparently trivial change in a comment can break the build.</p> </li> <li> <p>Did you <code>git add</code> all new files?</p> </li> <li> <p>Did you add regression tests for your change?</p> </li> <li> <p>Did you run those new regression tests?</p> </li> </ul> <p>If you are unsure of any of these things but still want to go ahead and create the PR, <strong>don’t!</strong></p> <p>If you have an actual reason to create a PR before the change is all done, make sure to create it in <code>DRAFT</code> mode. The bot won’t add the <code>rfr</code> label or send emails to labeled <a href="https://openjdk.org/bylaws#group">Groups</a> as long as the PR is in <code>DRAFT</code> mode.</p> <h2 id="life-of-a-pr">Life of a PR</h2> <ol> <li> <p><strong>Make sure the PR is reviewable</strong></p> <p>There are changes that span across several areas, for example wide spread cleanups or the introduction of a new language feature. Accordingly, the number of lines of code touched can be quite large, which makes it harder to review the entire PR. In such cases, it may make sense to split the change into several PRs, most commonly by grouping them by module or area.</p> </li> <li> <p><strong>Make sure you target the correct branch</strong></p> <p>Many project repositories have several branches. Make sure your PR targets the correct one. This is of course especially important when not targeting the default branch. At the top of your PR, right below the title, it will say “NNN wants to merge X commit(s) into [branch]”. Typical red flags to watch out for are if your PR seems to include commits or changed files that shouldn’t be part of your integration. E.g. Seeing the “Start of release updates for JDK N” when backporting something to JDK N-1 is a bad sign.</p> </li> <li> <p><strong>Set a correctly formatted title</strong></p> <p>The title of the PR should be of the form “<code>nnnnnnn: Title of JBS issue</code>” where <code>nnnnnnn</code> is the JBS issue id of the main JBS issue that is being fixed, and the <code>Title of JBS issue</code> is the exact title of the issue as written in JBS. In fact, the title can be set to <em>only</em> the JBS issue id (<code>nnnnnnn</code>) in which case the bot will fetch the title from JBS automatically. If you are creating a backport PR, see <a href="#using-the-skara-tooling-to-help-with-backports">Using the Skara tooling to help with backports</a> for more details on the title requirements.</p> </li> <li> <p><strong>Write a useful description</strong></p> <p>The description of the PR should state what problem is being solved and shortly describe how it’s solved. <a href="https://openjdk.org/bylaws#reviewer">Reviewers</a> and other interested readers are referred to the text in the JBS issue for details, but the description should be enough to give an overview. This assumes there’s useful information in the JBS issue, like an evaluation etc. If not, add it.</p> <p>Remember that the description is included in many emails sent to lists with many receivers, so a too long description can cause a lot of noise, while of course a too short description won’t give the reader enough information to perform the review. If you have a lot of information you wish to add to your PR, like performance evaluations, you can put that in a separate comment in the PR.</p> </li> <li> <p><strong>Finish the change before publishing it</strong></p> <p>Each update to a published PR will result in emails being sent to all relevant lists. This is per design and it’s how we want it to be, but it also mean that if you publish a PR before you have gone through the final check mentioned above, and later find that a few more updates are necessary, a lot of people will get a lot of emails.</p> </li> <li> <p><strong>Make sure all relevant <a href="https://openjdk.org/bylaws#group">Groups</a> are included</strong></p> <p>The bot will make an attempt to include the <a href="https://openjdk.org/bylaws#group">Groups</a> that need to review your change based on the location of the source code you have changed. There may be aspects of your change that are relevant to other <a href="https://openjdk.org/bylaws#group">Groups</a> as well, and the mapping from source to <a href="https://openjdk.org/bylaws#group">Groups</a> isn’t always perfect, so make sure all relevant <a href="https://openjdk.org/bylaws#group">Groups</a> have been included, and add new labels using <a href="https://wiki.openjdk.org/display/SKARA/Pull+Request+Commands#PullRequestCommands-/label"> <code>/label</code></a> if needed. Consult the <a href="#code-owners">Code Owners</a> section if you are unsure of who owns the code you are changing.</p> </li> <li> <p><strong>Allow enough time for review</strong></p> <p>In general all PRs should be open for at least 24 hours to allow for reviewers in all time zones to get a chance to see it. It may actually happen that even 24 hours isn’t enough. Take into account weekends, holidays, and vacation times throughout the world and you’ll realize that a change that requires more than just a trivial review may have to be open for a while. In some areas [trivial] changes are allowed to be integrated without the 24 hour delay. Ask your reviewers if you think this applies to your change.</p> </li> <li> <p><strong>Get the required reviews</strong></p> <p>At least one <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a> knowledgeable in each area being changed must approve every change. A change may therefore require multiple <a href="https://openjdk.org/bylaws#reviewer">Reviewers</a> because it affects multiple areas. Some areas (e.g. Client and HotSpot) require two reviewers in most cases, so be sure to read the relevant <a href="https://openjdk.org/bylaws#group">OpenJDK Group</a> pages for advice or ask your <a href="https://openjdk.org/bylaws#sponsor">Sponsor</a>.</p> <p>Be open to comments and polite in replies. Remember that the reviewer wants to improve the world just as much as you do, only in a slightly different way. If you don’t understand some comment, ask the reviewer to clarify. Accept authority when applicable. If you’re making changes in an area where you’re not the area expert, acknowledge that your reviewers may be. Take their advice seriously, even if it is to not make the change. There are many reasons <a href="#why-is-my-change-rejected">why a change may get rejected</a>. And you did read the section [Things to consider before changing OpenJDK code], right?</p> </li> <li> <p><strong>Updating the PR</strong></p> <p>You may need to change the code in response to review comments. To do this, simply commit new changes and push them onto the PR branch. The PR will be updated automatically. Multiple commits to the branch will be squashed into a single commit when the PR is eventually integrated.</p> <p>If the set of files in the PR has changed, this may affect the <a href="https://openjdk.org/bylaws#group">Groups</a> that need to review the PR. Make sure to adjust the PR labels accordingly.</p> <p>If you want to update the title of the PR, remember that the one and only truth is the JBS issue, so the title must first be changed there.</p> </li> <li> <p><strong>Merge the latest changes</strong></p> <p>If your PR is out for review for a longer time it’s a good habit to pull from the target repository regularly to keep the change up to date. This will make it easier to review the change and it will help you find issues caused by other changes sooner. Typically this involves fetching changes from the <code>master</code> branch of the main JDK repo, merging them into your local branch, resolving conflicts if necessary, and then pushing these changes to the PR branch. Pushing additional commits and merges into the PR branch is fine; they will be squashed into a single commit when the PR is integrated. Avoid rebasing changes, and prefer merging instead.</p> <p>If your PR is targeting some other branch than <code>master</code>, make sure to merge the correct upstream branch (the target branch). Verify that your PR doesn’t include changes from some other branch (e.g. <code>master</code>) that aren’t supposed to be there.</p> <p>If there are upstream changes that might affect your change, it’s likely a good idea to rerun relevant testing as well. The <a href="#github-actions">GHA testing</a> that’s done automatically by <a href="https://github.com">GitHub</a> should only be seen as a smoke test that finds the most severe problems with your change. It’s highly unlikely that it will test your actual change in any greater detail - or even at all execute the code that you have changed in most cases.</p> </li> <li> <p><strong>Integrate your change</strong></p> <p>When you have the required reviews and have made sure all relevant areas have had a chance to look at your change, integrate by entering the command <a href="https://wiki.openjdk.org/display/SKARA/Pull+Request+Commands#PullRequestCommands-/integrate"> <code>/integrate</code></a> in a comment on the PR. If you are not yet a <a href="https://openjdk.org/bylaws#committer">Committer</a> in the <a href="https://openjdk.org/bylaws#project">Project</a>, ask your <a href="https://openjdk.org/bylaws#sponsor">Sponsor</a> to enter the command <a href="https://wiki.openjdk.org/display/SKARA/Pull+Request+Commands#PullRequestCommands-/sponsor"> <code>/sponsor</code></a> in the PR as well in order for your change to be allowed to be integrated.</p> </li> <li> <p><strong>After integration</strong></p> <p>After you have integrated your change you are expected to stay around in case there are any issues with it. As mentioned above, you are expected to have run all relevant testing on your change before integrating your PR, but regardless of how thorough you test it, things might slip through. After your change has been integrated an automatic pipeline of tests is triggered and your change will be tested on a variety of platforms and in a variety of different modes that the JDK can be executed in. A change that causes failures in this testing may be backed out if a fix can’t be provided fast enough, or if the developer isn’t responsive when noticed about the failure. Note that this directive should be interpreted as “it’s a really bad idea to integrate a change the last thing you do before bedtime, or the day before going on vacation”.</p> </li> </ol> <h2 id="webrevs">Webrevs</h2> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://github.com/openjdk/webrev">Webrev Source Repository</a></li> <li><a href="https://mail.openjdk.org/pipermail/webrev-dev/">Webrev Mailing List</a></li> </ul> </div> <p>As all <a href="https://openjdk.org/bylaws#project">OpenJDK Projects</a> are hosted on <a href="https://github.com">GitHub</a>, most code reviews takes place there. When you publish a PR to an OpenJDK repository the corresponding JBS issue will get a link to the code review in the PR, making this the natural place to go for review. OpenJDK do however provide other tools and infrastructure for code reviews as well: The <strong>webrevs</strong>.</p> <p>Webrev refers to both the tool used to create them and its output. The script, <a href="https://github.com/openjdk/webrev/blob/master/webrev.ksh"><code>webrev.ksh</code></a>, is maintained in the <a href="../projects/code-tools">Code Tools Project</a>. Please note that this version of webrev is for use with mercurial and won’t work with the git based repositories. You don’t actually need tools like this anymore unless you want to host code reviews in other locations than <a href="https://github.com">GitHub</a>.</p> <p>On the GitHub reviews you will find links to webrevs. These are automatically generated by the bot and are provided as a complement for those who prefer this style of code review. Many OpenJDK developers are used to the webrevs as this was the default way to provide code for review before OpenJDK moved to <a href="https://github.com">GitHub</a>. Though webrevs are mainly deprecated today, they used to be a central part of OpenJDK development and you may still see people use the word as a synonym for code review, so they do deserve to be mentioned here as well.</p> <h2 id="file-storage-for-openjdk-artifacts---cr.openjdk.org">File storage for OpenJDK artifacts - <code>cr.openjdk.org</code></h2> <p>The <code>cr.openjdk.org</code> server provides storage and display of code review materials such as webrevs and other artifacts related to the OpenJDK Community. This area can also be used to store design documents and other documentation related OpenJDK but not related to any specific <a href="https://openjdk.org/bylaws#project">Project</a> that have an OpenJDK wiki space for such purposes.</p> <p>Any OpenJDK <a href="https://openjdk.org/bylaws#author">Author</a> can publish materials on the <code>cr.openjdk.org</code> server. Users can upload files to temporary storage using secure methods (<code>rsync</code>, <code>scp</code>, and <code>sftp</code>).</p> <p>This site is for open source materials related to the OpenJDK Community only. Users uploading inappropriate materials will lose access and the material will be deleted. Please review the <a href="https://openjdk.org/legal/terms.html">Terms of Use</a> before using this server.</p> <h3 id="get-your-ssh-key-installed">Get your SSH key installed</h3> <p>To use <code>cr.openjdk.org</code> you’ll need to get an SSH key installed. See <a href="#generating-an-ssh-key">Generating an SSH key</a> for guidance on how to generate a key. Your public key (<code>~/.ssh/id_rsa.pub</code>) should be mailed as an attachment along with your JDK username to <a href="mailto:keys@openjdk.org">keys@openjdk.org</a>. An administrator will install your key on the server and notify you on completion. This process may take a couple of days.</p> <div class="note"> <p>Users behind a SOCKS firewall can add a directive to the <code>~/.ssh/config</code> file to connect to the OpenJDK server:</p> <pre><code>Host *.openjdk.org ProxyCommand /usr/lib/ssh/ssh-socks5-proxy-connect -h [socks_proxy_address] %h %p</code></pre> <p>See the <code>ssh-socks5-proxy-connect</code> man page and <code>ssh-config</code> man page for more information. Other systems may require proxy access via other programs. Some Linux distributions provide the <code>corkscrew</code> package which provides ssh access through HTTP proxies.</p> <p><strong>It’s recommended that all users check with their network administrators before installing any kind of TCP forwarding tool on their network. Many corporations and institutions have strict security policies in this area.</strong></p> </div> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="reviewing-and-sponsoring-a-change">Reviewing and Sponsoring a Change</h1> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/about-pull-request-reviews"> GitHub Docs on pull requests reviews</a></li> </ul> </div> <p>Two of the most important contributions you can make in the OpenJDK community are to review and sponsor changes for other developers. All changes needs to be reviewed. Many changes even need to be reviewed by more than one person. This means that in order to enable a fast-pased development experience, all developers need to review more changes then they produce themself.</p> <p>If you are new to an area, reviewing changes is also a great way to learn the code and see what general styles and types of changes are relevant in the area. Be mindful though, if you don’t know the area well you should state this in your review comments.</p> <p>New developers in the OpenJDK community don’t have the permissions needed to integrate changes to the repositories. This is a feature that ensures that all developers get familiar with the code, processes, and community before being allowed to actually make changes. To get their first changes in, the new Contributor needs the help of a Sponsor. The Sponsor’s role is to offer constructive advice and eventually integrate the sponsored contribution into the repository.</p> <p>Sponsoring new contributions is an important activity - it’s how the engineering culture of a project gets passed on from the core group to new Contributors, from one generation to the next. Take pride in the value you provide to Contributors. Their success reflects well on you.</p> <p>There are many different reasons to sponsor a change and depending on the situation the exact steps involved may differ significantly. An experienced developer hired into a larger team of OpenJDK developers is likely to get much of the required information by osmosis and will likely need less help from a sponsor than the enthusiast sitting at home with no prior experience of large scale software development. This text aims to highlight the steps involved in sponsoring a change but can’t cover all possible scenarios. As always, common sense takes precedence where the assumptions made here doesn’t apply to your use case.</p> <h2 id="responsibilities-of-a-reviewer">Responsibilities of a Reviewer</h2> <p>As a <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a> you have a responsibility to make sure changes are sound and align with the general direction of the area. If you, as a <a href="https://openjdk.org/bylaws#reviewer">Reviever</a>, review a change in an area that you don’t know well you probably shouldn’t be the one to approve the change.</p> <p><a href="https://openjdk.org/bylaws#reviewer">Reviewers</a> should be aware that they take full responsibility for the appropriateness and correctness of any changes in their area of expertise. If something goes wrong (e.g., the build breaks) and the change’s author is unavailable, they may be asked to deal with the problem. Potential <a href="https://openjdk.org/bylaws#reviewer">Reviewers</a> are encouraged to refuse to review code for which they aren’t qualified.</p> <p><a href="https://openjdk.org/bylaws#reviewer">Reviewers</a> should examine not only the code being added or changed but also the relevant unit or regression tests. If no tests are being added for a change that isn’t already covered by existing tests and have the appropriate <span class="jbs-label">noreg-</span> label, the <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a> should question this.</p> <p>As a <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a>, Contributors will look up to you for guidance to get their contributions into the project - your actions will determine whether Contributors will feel welcome and want to engage further with the project beyond their initial attempt, or not. Let’s not lose enthusiastic, engaged and technically competent Contributors due to a lack of communication. If you see a request in your area of expertise and you can’t address it, at least acknowledge receipt of the request and provide an estimate for when you’ll be able to give it your attention. A frank explanation of your time constraints or commitments will be appreciated and respected.</p> <h2 id="reviewing-a-change-on-github">Reviewing a change on GitHub</h2> <p>Code reviews in OpenJDK happens on <a href="https://github.com/openjdk">GitHub</a>. This guide will hint at the most common steps to perform a review but it’s not a complete documentation of all features. For official documentation see the <a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/about-pull-request-reviews"> GitHub Docs</a>.</p> <p>When you arrive at a pull request there are a few different sections that you can browse through, Conversation, Commits, Checks, and Files changed. We will look at the first and the last of these.</p> <h3 id="conversation">Conversation</h3> <p>The Conversation section is where all discussion around the PR happens. Note that this section is intended for technical discussion around the actual implementation of a change. This is in general not the place to discuss the appropriateness of the change or have overarching design discussions, that should happen on the appropriate <a href="#mailing-lists">mailing lists</a>. Yes, PR comments will be sent to the mailing lists as well, but it’s unlikely that all the right people will see it. PR mails sent to the mailing lists will have a subject indicating that it’s about the specific implementation in the PR. If the discussion is larger than just about the specific implementation, for instance around the design or future of the feature, then a much larger audience needs to be made aware of the discussion. A separate email thread with a proper subject is preferred in such cases.</p> <p>You can either reply to existing comments by using the text field beneath each comment, or add a new comment by scrolling to the bottom of the page and use the larger text field where it says “Leave a comment”.</p> <p>Reviews take time for everyone involved. Your opinions are much appreciated as long as they are on-topic and of a constructive nature. A comment of the form “I don’t like this” won’t help anyone to improve the change. Instead express what it is that you don’t like and give examples of how to do it differently. Always be polite and make sure you read through all previous comments before adding your own, the answer you are looking for may already have been given.</p> <div class="note"> <p>Note that GitHub will collapse comments if there are many of them, and if an issue is marked as resolved. This means that you have to be observant and may have to dig around a bit to find all comments in the PR.</p> </div> <p>Never ask the author of a change to fix unrelated issues in the code that you find during your review. Such issues should be handled through a separate JBS issue and PR.</p> <h3 id="files-changed">Files changed</h3> <p>The Files changed-section is where the actual change is presented. On the left hand side there’s a list of all files changed. This is useful to get a quick overview and to see if the change touches an area that you need to review.</p> <p>The diff view is pretty straight forward, red stuff has been removed, green stuff has been added. You can configure (among other things) if you want a unified diff or a split view, if you want to hide whitespace changes, what types of files you want to show, and if you want to show the entire change or just what’s happened since your last review.</p> <p>When you hover the text in the change a blue square with a plus sign pops up to the left of the line. Click it to add a comment about the change on the corresponding line. When you create your first comment you have the option to simply add a single comment or to start a review. In general you want to start a review so that all your comments are gathered in the same context when emails are sent out etc. You can also attach a comment to a file rather than to a specific line in the file by using the speech bubble icon at the top right.</p> <p>When a complete file has been reviewed there’s a “viewed” checkbox at the top right that can be used to hide the files that you are done with. This is useful for changes that involve many files.</p> <p>Once you have looked through all the changes and added all your comments, the green button at the top right of the screen “Review changes” is used to finish your review. You can add a final comment to sum up your findings and then choose whether you just want to provide your comments, if you want to approve the changes, or request that changes are done before the change can be approved. Finally click “Submit review” to publish your thoughts.</p> <h3 id="trivial-changes">Trivial changes</h3> <p>A change that is small, well contained, and that makes no semantic changes can be called <em>trivial</em>. Typical examples are fixing obvious typos or renaming a local identifier. A trivial change can also be integrating an already-reviewed change that was missed in an earlier integration (e.g., forgot to add a file) or generated changes like a <a href="#backing-out-a-change"><code>git revert</code></a>. It’s up to the author of a change to claim that the change is trivial in the RFR, and it’s up to the <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a> whether to approve such a claim. A change is trivial only if the <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a> agrees that it is. A trivial change doesn’t need to wait 24 hours before being pushed, and it only needs one <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a>, even in areas where stricter rules for integration normally apply.</p> <h2 id="volunteering-to-sponsor-a-contribution">Volunteering to sponsor a contribution</h2> <p>In an ideal situation opportunities to sponsor contributions occur in the OpenJDK mail lists. Since Contributors are encouraged to discuss their intended changes before they submit a patch, the ideal time to declare your sponsorship is during that initial conversation. As a Sponsor you should offer advice and collaborate with the Contributor as necessary to produce a high-quality patch. In addition to sponsoring changes to code you regularly maintain, there may be other areas where you can serve as a Sponsor.</p> <p>After publicly committing to sponsoring a contribution, you need to “claim the sponsorship request” in <a href="#jbs---jdk-bug-system">JBS</a> unless the Contributor already has a JBS account and can assign the bug to themself. To do that you need to perform three steps:</p> <ul> <li>Assign the bug to yourself.</li> <li>Add a comment providing the name of the Contributor and a summary of the approach to solving the problem.</li> <li>Set the bug’s <span class="jbs-field">Status</span> to <span class="jbs-value">In Progress</span>.</li> </ul> <p>If the contribution doesn’t already have an associated OpenJDK bug then create one in <a href="#jbs---jdk-bug-system">JBS</a>.</p> <p>It should be noted that claiming the sponsorship can take many other forms. In cases where a change has been discussed, or a starter bug has been picked up and fixed even though a sponsor hasn’t been identified yet it may be as simple as just showing up at the PR and sponsor the change once it’s been reviewed.</p> <h2 id="responsibilities-of-a-sponsor">Responsibilities of a sponsor</h2> <p>As a sponsor, you aren’t technically required to review the change, other Reviewers may already have looked at it or signed up to review. But it will be your name on the commit so you should do whatever you feel is needed to be comfortable with that. You may need to work with the Contributor to make any necessary changes, until you and the Contributor are satisfied with the result, and you are satisfied that the proposed contribution will pass any relevant review and testing. That may take more than one iteration in the worst case. You may also need to help out with any process or practical questions around the OCA, GitHub PRs, and specific requirements in the area or project.</p> <p>To integrate the change the Contributor should use the command <code>/integrate</code> on the PR as prompted by the bots. Once that is done, you as a sponsor enter the command <code>/sponsor</code> in a comment on the PR.</p> <p>Once the change has been integrated you may need to keep an eye out for any reported test failures and be prepared to investigate if such failures stem from the change you sponsored, and if so, work with the Contributor to resolve the issue.</p> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="backporting">Backporting</h1> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://openjdk.org/projects/jdk-updates/approval.html">Push approval for JDK updates</a></li> <li><a href="https://wiki.openjdk.org/display/SKARA/Backports">Skara documentation on backports</a></li> </ul> </div> <p>Development of the latest version of the JDK often results in bug fixes that might be interesting to include in some of the JDK Update releases still being maintained or in a feature release stabilization branch. Moving a fix from a more recent release train (e.g. JDK 21) to an older release train (e.g. JDK 17) is called <em>backporting</em>.</p> <p>The guideline for what to backport into a specific release will vary over the lifetime of that release. Initially more fixes are expected to be backported as new features and large changes introduced in a mainline release stabilize. Over time the focus will shift from stabilization to keeping it stable - the release will go into maintenance mode. This means that bug fixes that require larger disruptive changes are more likely to be made in mainline and backported to more recent release trains only, and not to older release trains.</p> <p>Over time it’s likely that the code base will diverge between mainline and any given update release, and the cost of backporting will increase. The cost in this case is not only the effort needed to perform the actual backport, but also the cost inferred by bugs introduced by the backport. This should be taken into consideration when deciding if a change should be backported or not. For more details on how to reason around what to backport, <a href="https://mail.openjdk.org/pipermail/jdk8u-dev/2020-June/012002.html"> this email from JDK 8 Updates Project lead Andrew Haley</a> has some guidelines for JDK 8u. The reasoning in this mail is specific to JDK 8u, but will in general apply to any JDK release in maintenance mode.</p> <p>Any change that originally required a CSR will require a new CSR to be backported unless the backport was covered by the initial CSR. Changes to Java SE specifications cannot be made in an update release without a Java SE Maintenance Release. CSR-related issues affect interfaces and behavior and must be very carefully scrutinized.</p> <h2 id="backporting-to-a-feature-release-stabilization-branch"> Backporting to a feature release stabilization branch</h2> <p>During ramp down of a feature release there are two branches of the mainline repository in play, the release stabilization branch for the outgoing release, and the <code>master</code> branch where the next release is being developed. Any change going into the release stabilization branch is likely to be desired in <code>master</code> as well. When making a change intended for both the stabilization branch and <code>master</code>, you should always create your pull request targeting <code>master</code> first, and then, once the pull request is integrated, backport the resulting commit to the release stabilization branch. For bug fixes that are <strong>only</strong> applicable to the release stabilization branch, regular pull requests targeting the stabilization branch should be created.</p> <p>Please note that special rules applies during ramp down regarding what can and can’t be included into the stabilization branch. See the <a href="#the-jdk-release-process">The JDK Release Process</a> for more information.</p> <h2 id="backporting-multiple-related-changes">Backporting multiple related changes</h2> <p>Ideally fixes should not be backported until there has been enough time for any regressions or follow-on issues to have been identified. Then, when looking to backport a fix the developer should look for both <span class="jbs-value">blocked by</span> and <span class="jbs-value">causes</span> links in order to understand the complete set of fixes that should be backported.</p> <p>When backporting a number of changes that are dependent on each other, like a change with a tail of bug fixes, it can sometimes seem attractive to merge all those commits into a single change to avoid backporting a broken change. Please don’t. The general recommendation is to backport each commit individually. There are several reasons for this recommendation.</p> <p>If, for instance, there are other changes between the original one and the followup fix(es) there may be a dependency on other changes that are unrelated to the issue itself. By merging the original change, the fix(es), and the unrelated changes to meet the dependency, a single very different change is created. It’s unlikely that this change will match the description in the single JBS issue used for the merged backport. Backporting each commit individually will preserve the git history and make it easy to figure out what has actually been backported.</p> <p>Testing each individual change is more likely to find issues than just testing the single merged change. It’s also easier and less error prone to use the <code>/backport</code> command on each commit instead of manually cherrypick and deal with the merges etc.</p> <p>And finally, if backporting each commit individually, the JBS records will clearly indicate that the followup changes have been backported as well. This is important as there is tooling that verifies that everything is done in the right way. That tooling will be confused if it can’t deduct from JBS what has happened.</p> <h2 id="working-with-backports-in-jbs">Working with backports in JBS</h2> <div class="box"> <p><span class="boxheader">Terminology</span></p> <p>Main issue - The top issue in a backport hierarchy. Eg. <a href="https://bugs.openjdk.org/browse/JDK-8272373">JDK-8272373</a> is a <em>main issue</em>, while <a href="https://bugs.openjdk.org/browse/JDK-8277498">JDK-8277498</a> and <a href="https://bugs.openjdk.org/browse/JDK-8277499">JDK-8277499</a> are <em>backport issues</em> of this main issue.</p> </div> <div style="text-align:center;"> <div class="figure"><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibWVybWFpZC0xNzM4MTkwNjU3MTAyIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgaGVpZ2h0PSIxNjEuNSIgc3R5bGU9Im1heC13aWR0aDogMzEzLjQ1M3B4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9IjAgMCAzMTMuNDUzMTI1IDE2MS41Ij48c3R5bGU+I21lcm1haWQtMTczODE5MDY1NzEwMiB7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O2ZpbGw6IzAwMDAwMDt9I21lcm1haWQtMTczODE5MDY1NzEwMiAuZXJyb3ItaWNvbntmaWxsOiM1NTIyMjI7fSNtZXJtYWlkLTE3MzgxOTA2NTcxMDIgLmVycm9yLXRleHR7ZmlsbDojNTUyMjIyO3N0cm9rZTojNTUyMjIyO30jbWVybWFpZC0xNzM4MTkwNjU3MTAyIC5lZGdlLXRoaWNrbmVzcy1ub3JtYWx7c3Ryb2tlLXdpZHRoOjJweDt9I21lcm1haWQtMTczODE5MDY1NzEwMiAuZWRnZS10aGlja25lc3MtdGhpY2t7c3Ryb2tlLXdpZHRoOjMuNXB4O30jbWVybWFpZC0xNzM4MTkwNjU3MTAyIC5lZGdlLXBhdHRlcm4tc29saWR7c3Ryb2tlLWRhc2hhcnJheTowO30jbWVybWFpZC0xNzM4MTkwNjU3MTAyIC5lZGdlLXBhdHRlcm4tZGFzaGVke3N0cm9rZS1kYXNoYXJyYXk6Mzt9I21lcm1haWQtMTczODE5MDY1NzEwMiAuZWRnZS1wYXR0ZXJuLWRvdHRlZHtzdHJva2UtZGFzaGFycmF5OjI7fSNtZXJtYWlkLTE3MzgxOTA2NTcxMDIgLm1hcmtlcntmaWxsOiM2NjY7c3Ryb2tlOiM2NjY7fSNtZXJtYWlkLTE3MzgxOTA2NTcxMDIgLm1hcmtlci5jcm9zc3tzdHJva2U6IzY2Njt9I21lcm1haWQtMTczODE5MDY1NzEwMiBzdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O30jbWVybWFpZC0xNzM4MTkwNjU3MTAyIC5sYWJlbHtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Y29sb3I6IzAwMDAwMDt9I21lcm1haWQtMTczODE5MDY1NzEwMiAuY2x1c3Rlci1sYWJlbCB0ZXh0e2ZpbGw6IzMzMzt9I21lcm1haWQtMTczODE5MDY1NzEwMiAuY2x1c3Rlci1sYWJlbCBzcGFue2NvbG9yOiMzMzM7fSNtZXJtYWlkLTE3MzgxOTA2NTcxMDIgLmxhYmVsIHRleHQsI21lcm1haWQtMTczODE5MDY1NzEwMiBzcGFue2ZpbGw6IzAwMDAwMDtjb2xvcjojMDAwMDAwO30jbWVybWFpZC0xNzM4MTkwNjU3MTAyIC5ub2RlIHJlY3QsI21lcm1haWQtMTczODE5MDY1NzEwMiAubm9kZSBjaXJjbGUsI21lcm1haWQtMTczODE5MDY1NzEwMiAubm9kZSBlbGxpcHNlLCNtZXJtYWlkLTE3MzgxOTA2NTcxMDIgLm5vZGUgcG9seWdvbiwjbWVybWFpZC0xNzM4MTkwNjU3MTAyIC5ub2RlIHBhdGh7ZmlsbDojZWVlO3N0cm9rZTojOTk5O3N0cm9rZS13aWR0aDoxcHg7fSNtZXJtYWlkLTE3MzgxOTA2NTcxMDIgLm5vZGUgLmxhYmVse3RleHQtYWxpZ246Y2VudGVyO30jbWVybWFpZC0xNzM4MTkwNjU3MTAyIC5ub2RlLmNsaWNrYWJsZXtjdXJzb3I6cG9pbnRlcjt9I21lcm1haWQtMTczODE5MDY1NzEwMiAuYXJyb3doZWFkUGF0aHtmaWxsOiMzMzMzMzM7fSNtZXJtYWlkLTE3MzgxOTA2NTcxMDIgLmVkZ2VQYXRoIC5wYXRoe3N0cm9rZTojNjY2O3N0cm9rZS13aWR0aDoyLjBweDt9I21lcm1haWQtMTczODE5MDY1NzEwMiAuZmxvd2NoYXJ0LWxpbmt7c3Ryb2tlOiM2NjY7ZmlsbDpub25lO30jbWVybWFpZC0xNzM4MTkwNjU3MTAyIC5lZGdlTGFiZWx7YmFja2dyb3VuZC1jb2xvcjp3aGl0ZTt0ZXh0LWFsaWduOmNlbnRlcjt9I21lcm1haWQtMTczODE5MDY1NzEwMiAuZWRnZUxhYmVsIHJlY3R7b3BhY2l0eTowLjU7YmFja2dyb3VuZC1jb2xvcjp3aGl0ZTtmaWxsOndoaXRlO30jbWVybWFpZC0xNzM4MTkwNjU3MTAyIC5jbHVzdGVyIHJlY3R7ZmlsbDpoc2woMCwgMCUsIDk4LjkyMTU2ODYyNzUlKTtzdHJva2U6IzcwNzA3MDtzdHJva2Utd2lkdGg6MXB4O30jbWVybWFpZC0xNzM4MTkwNjU3MTAyIC5jbHVzdGVyIHRleHR7ZmlsbDojMzMzO30jbWVybWFpZC0xNzM4MTkwNjU3MTAyIC5jbHVzdGVyIHNwYW57Y29sb3I6IzMzMzt9I21lcm1haWQtMTczODE5MDY1NzEwMiBkaXYubWVybWFpZFRvb2x0aXB7cG9zaXRpb246YWJzb2x1dGU7dGV4dC1hbGlnbjpjZW50ZXI7bWF4LXdpZHRoOjIwMHB4O3BhZGRpbmc6MnB4O2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTJweDtiYWNrZ3JvdW5kOmhzbCgtMTYwLCAwJSwgOTMuMzMzMzMzMzMzMyUpO2JvcmRlcjoxcHggc29saWQgIzcwNzA3MDtib3JkZXItcmFkaXVzOjJweDtwb2ludGVyLWV2ZW50czpub25lO3otaW5kZXg6MTAwO30jbWVybWFpZC0xNzM4MTkwNjU3MTAyIDpyb290ey0tbWVybWFpZC1mb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7fTwvc3R5bGU+PGc+PGcgY2xhc3M9Im91dHB1dCI+PGcgY2xhc3M9ImNsdXN0ZXJzIj48L2c+PGcgY2xhc3M9ImVkZ2VQYXRocyI+PGcgY2xhc3M9ImVkZ2VQYXRoIExTLW1haW4gTEUtYmFja3BvcnQxIiBpZD0iTC1tYWluLWJhY2twb3J0MSIgc3R5bGU9Im9wYWNpdHk6IDE7Ij48cGF0aCBjbGFzcz0icGF0aCIgZD0iTTEyNy43MTUyMjcwNzM1OTgxMyw0Ni41TDExOS4xMTIyOTg2MDI5OTg0NSw1Mi4yMDgzMzMzMzMzMzMzMzZDMTEwLjUwOTM3MDEzMjM5ODc2LDU3LjkxNjY2NjY2NjY2NjY2NCw5My4zMDM1MTMxOTExOTkzOSw2OS4zMzMzMzMzMzMzMzMzMyw4NC43MDA1ODQ3MjA1OTk3LDgwLjc1Qzc2LjA5NzY1NjI1LDkyLjE2NjY2NjY2NjY2NjY3LDc2LjA5NzY1NjI1LDEwMy41ODMzMzMzMzMzMzMzMyw3Ni4wOTc2NTYyNSwxMDkuMjkxNjY2NjY2NjY2NjdMNzYuMDk3NjU2MjUsMTE1IiBtYXJrZXItZW5kPSJ1cmwoI2Fycm93aGVhZDEwKSIgc3R5bGU9ImZpbGw6bm9uZSI+PC9wYXRoPjxkZWZzPjxtYXJrZXIgaWQ9ImFycm93aGVhZDEwIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJzdHJva2VXaWR0aCIgbWFya2VyV2lkdGg9IjgiIG1hcmtlckhlaWdodD0iNiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgMCBMIDEwIDUgTCAwIDEwIHoiIGNsYXNzPSJhcnJvd2hlYWRQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyI+PC9wYXRoPjwvbWFya2VyPjwvZGVmcz48L2c+PGcgY2xhc3M9ImVkZ2VQYXRoIExTLW1haW4gTEUtYmFja3BvcnQyIiBpZD0iTC1tYWluLWJhY2twb3J0MiIgc3R5bGU9Im9wYWNpdHk6IDE7Ij48cGF0aCBjbGFzcz0icGF0aCIgZD0iTTE4NS43Mzc4OTc5MjY0MDE4Nyw0Ni41TDE5NC4zNDA4MjYzOTcwMDE1Niw1Mi4yMDgzMzMzMzMzMzMzMzZDMjAyLjk0Mzc1NDg2NzYwMTIzLDU3LjkxNjY2NjY2NjY2NjY2NCwyMjAuMTQ5NjExODA4ODAwNiw2OS4zMzMzMzMzMzMzMzMzMywyMjguNzUyNTQwMjc5NDAwMzQsODAuNzVDMjM3LjM1NTQ2ODc1LDkyLjE2NjY2NjY2NjY2NjY3LDIzNy4zNTU0Njg3NSwxMDMuNTgzMzMzMzMzMzMzMzMsMjM3LjM1NTQ2ODc1LDEwOS4yOTE2NjY2NjY2NjY2N0wyMzcuMzU1NDY4NzUsMTE1IiBtYXJrZXItZW5kPSJ1cmwoI2Fycm93aGVhZDExKSIgc3R5bGU9ImZpbGw6bm9uZSI+PC9wYXRoPjxkZWZzPjxtYXJrZXIgaWQ9ImFycm93aGVhZDExIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJzdHJva2VXaWR0aCIgbWFya2VyV2lkdGg9IjgiIG1hcmtlckhlaWdodD0iNiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgMCBMIDEwIDUgTCAwIDEwIHoiIGNsYXNzPSJhcnJvd2hlYWRQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyI+PC9wYXRoPjwvbWFya2VyPjwvZGVmcz48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWxzIj48ZyBjbGFzcz0iZWRnZUxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg3Ni4wOTc2NTYyNSw4MC43NSkiIHN0eWxlPSJvcGFjaXR5OiAxOyI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTY4LjA5NzY1NjI1LC05LjI1KSIgY2xhc3M9ImxhYmVsIj48cmVjdCByeD0iMCIgcnk9IjAiIHdpZHRoPSIxMzYuMTk1MzEyNSIgaGVpZ2h0PSIxOC41Ij48L3JlY3Q+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjEzNi4xOTUzMTI1IiBoZWlnaHQ9IjE4LjUiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBpZD0iTC1MLW1haW4tYmFja3BvcnQxIiBjbGFzcz0iZWRnZUxhYmVsIEwtTFMtbWFpbicgTC1MRS1iYWNrcG9ydDEiPmJhY2twb3J0IHRvIEpESyAxNzwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyMzcuMzU1NDY4NzUsODAuNzUpIiBzdHlsZT0ib3BhY2l0eTogMTsiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC02OC4wOTc2NTYyNSwtOS4yNSkiIGNsYXNzPSJsYWJlbCI+PHJlY3Qgcng9IjAiIHJ5PSIwIiB3aWR0aD0iMTM2LjE5NTMxMjUiIGhlaWdodD0iMTguNSI+PC9yZWN0Pjxmb3JlaWduT2JqZWN0IHdpZHRoPSIxMzYuMTk1MzEyNSIgaGVpZ2h0PSIxOC41Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gaWQ9IkwtTC1tYWluLWJhY2twb3J0MiIgY2xhc3M9ImVkZ2VMYWJlbCBMLUxTLW1haW4nIEwtTEUtYmFja3BvcnQyIj5iYWNrcG9ydCB0byBKREsgMTE8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjxnIGNsYXNzPSJub2RlcyI+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCIgaWQ9ImZsb3djaGFydC1tYWluLTciIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE1Ni43MjY1NjI1LDI3LjI1KSIgc3R5bGU9Im9wYWNpdHk6IDE7Ij48cmVjdCByeD0iNSIgcnk9IjUiIHg9Ii01NS42Mjg5MDYyNSIgeT0iLTE5LjI1IiB3aWR0aD0iMTExLjI1NzgxMjUiIGhlaWdodD0iMzguNSIgY2xhc3M9ImxhYmVsLWNvbnRhaW5lciI+PC9yZWN0PjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwwKSI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQ1LjYyODkwNjI1LC05LjI1KSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjkxLjI1NzgxMjUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkpESy04MjcyMzczPC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQiIGlkPSJmbG93Y2hhcnQtYmFja3BvcnQxLTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDc2LjA5NzY1NjI1LDEzNC4yNSkiIHN0eWxlPSJvcGFjaXR5OiAxOyI+PHJlY3Qgcng9IjUiIHJ5PSI1IiB4PSItNTUuNjI4OTA2MjUiIHk9Ii0xOS4yNSIgd2lkdGg9IjExMS4yNTc4MTI1IiBoZWlnaHQ9IjM4LjUiIGNsYXNzPSJsYWJlbC1jb250YWluZXIiPjwvcmVjdD48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsMCkiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC00NS42Mjg5MDYyNSwtOS4yNSkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSI5MS4yNTc4MTI1IiBoZWlnaHQ9IjE4LjUiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij5KREstODI3NzQ5ODwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IiBpZD0iZmxvd2NoYXJ0LWJhY2twb3J0Mi05IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyMzcuMzU1NDY4NzUsMTM0LjI1KSIgc3R5bGU9Im9wYWNpdHk6IDE7Ij48cmVjdCByeD0iNSIgcnk9IjUiIHg9Ii01NS42Mjg5MDYyNSIgeT0iLTE5LjI1IiB3aWR0aD0iMTExLjI1NzgxMjUiIGhlaWdodD0iMzguNSIgY2xhc3M9ImxhYmVsLWNvbnRhaW5lciI+PC9yZWN0PjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwwKSI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQ1LjYyODkwNjI1LC05LjI1KSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjkxLjI1NzgxMjUiIGhlaWdodD0iMTguNSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPkpESy04Mjc3NDk5PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9nPjwvc3ZnPg==" alt="" /> <p class="caption">Example of backport hierarchy</p> </div> </div> <p>In general there’s no need to create backport issues in JBS manually. All work that’s done in JBS in preparation for a backport (requesting approvals etc) is done in the main issue. The backport issue will be created automatically by the bots when you integrate the change to the source code repository.</p> <p>There can be cases where it’s desirable to create a backport issue before the fix is done, e.g. if a CSR needs to be filed. In these cases set the <span class="jbs-field">Fix Version/s</span> of the backport to <code>N</code> or <code>N-pool</code>, where <code>N</code> is the release train the backport is targeting. E.g. <code>17-pool</code>. Please note that even if a backport issue is created ahead of time, all work done in JBS for approvals and similar is still done in the main issue.</p> <p>Obviously it’s possible to set the <span class="jbs-field">Fix Version/s</span> to the exact release the backport is targeting, but in general this isn’t recommended unless you are targeting a feature release in ramp down. When a change is integrated to an update release repository, the bots will look at the main issue as indicated in the PR title, and look for backports with the current <code>N.0.x</code> release version as <span class="jbs-field">Fix Version/s</span>, if no such backport is found they will look for <code>N-pool</code>, and if that isn’t found either, a new backport issue will be created. This means that if the backport has an exact <span class="jbs-field">Fix Version/s</span> set, but is delayed and misses the release indicated by this <span class="jbs-field">Fix Version/s</span>, a new, superfluous backport issue is created with a small mess as the result. (See <a href="#how-to-fix-an-incorrect-backport-creation-in-jbs">How to fix an incorrect backport creation in JBS</a>.)</p> <p>Setting the <span class="jbs-field">Fix Version/s</span> of a backport targeted to an update release to <code>N</code> is always wrong. JDK <code>N</code> has already been released (or it wouldn’t be an update release) and can’t get any more fixes.</p> <h2 id="requesting-approvals-for-backports">Requesting approvals for backports</h2> <p>In order to be allowed to integrate a change to one of the OpenJDK update development repositories (e.g. <a href="https://github.com/openjdk/jdk17u-dev"><code>jdk17u-dev</code></a>), an approval is required. The <a href="https://openjdk.org/projects/jdk-updates/approval.html">official process for how to request push approval for a backport</a> describes in detail how to work with JBS when requesting approvals. In short, there’s a label <span class="jbs-label">jdk<release>u-fix-request</span> that should be added to the main JBS issue. Also put a motivation as to why the issue needs to be backported as a comment in the main issue. Once the label and motivation has been added, wait for the maintainers of the release to approve your request. The approval will be indicated with a label, <span class="jbs-label">jdk<release>u-fix-yes</span>, added to the main issue.</p> <p>If the update release is in ramp down, changes are integrated to the release repository (e.g. <a href="https://github.com/openjdk/jdk17u"><code>jdk17u</code></a>). During ramp down the bar to get changes in is significantly higher and fixes need to be approved with <span class="jbs-label">jdk<release>u-critical-request</span> / <span class="jbs-label">jdk<release>u-critical-yes</span>.</p> <p>If your request to backport a change is denied, but you for some reason already created the backport issue in JBS (why?!), the backport issue should be closed as <span class="jbs-value">Won’t Fix</span>.</p> <h2 id="using-the-skara-tooling-to-help-with-backports">Using the Skara tooling to help with backports</h2> <p>The Skara tooling includes support for backports. <a href="https://wiki.openjdk.org/display/SKARA/Backports">The official Skara documentation</a> describes in detail how to work with the tooling to create backport PRs on <a href="https://github.com">GitHub</a> or using the CLI tools. As described in the documentation, the <a href="https://wiki.openjdk.org/display/SKARA/Commit+Commands#CommitCommands-/backport"> <code>/backport</code></a> command can be used on a commit or a PR to create the backport PR:</p> <pre><code>/backport jdk21u-dev /backport jdk jdk23 /backport :jdk23</code></pre> <p>In the first example we backport the change to the JDK 21 update release. To backport to other update releases, replace <code>jdk21u</code> with the corresponding name for the target update repository.</p> <p>The second and third example above will backport the change to a stabilization branch, in this case JDK 23. As before <code>jdk</code> is the name of the target repository, and <code>jdk23</code> is the name of the stabilization branch.</p> <p>Using the <code>/backport</code> command is the recommended way to perform backports as the tooling will automatically handle all the necessary steps in the background. If a backport PR is manually created, set the PR title to <code>Backport <original commit hash></code>. This ensures that the bots will recognize it as a backport as opposed to a main fix specifically targeting an older release. One can tell whether or not the bots recognized a PR as a backport by the <span class="label">backport</span> label being added if it’s recognized.</p> <h2 id="how-to-fix-an-incorrect-backport-creation-in-jbs">How to fix an incorrect backport creation in JBS</h2> <p>If an issue is targeted to a release and a fix referring to that issue is integrated to a different release repository, then a backport issue is automatically created in JBS. Usually this is a “good thing”, e.g., when you are backporting a fix to an earlier release, but not always… If the main issue is targeted to a later release (due to schedule planning) but someone finds the time to fix that issue in the current release, or if the main issue is targeted to a feature release in ramp down and the fix is integrated to the master branch, then the issue should be retargeted to the correct release before integrating the fix. However, sometimes we forget.</p> <p>Here’s how to fix that:</p> <div class="note"> <p>In this example a fix was integrated to JDK N+1 (the mainline master branch) while the JBS bug was targeted to JDK N (a feature release in ramp down). The same procedure can be used in the opposite situation, when a fix has been integrated to JDK N when the JBS bug was targeted to JDK N+1, by switching N and N+1 below. Remember, to keep the record clean for the future, what matters the most is that the <strong>bug id used in the commit comment is the main bug</strong>, and that <strong>the “backports”</strong> (regardless of if they are to earlier or later releases) <strong>are Backport type issues of that main issue</strong>. Also make sure there are never more than one Backport issue of the same main issue targeted to any given release.</p> </div> <ol> <li> <p>Reopen the <em>backport</em> issue that was created automatically</p> <ul> <li>Use a comment like the following (in the reopen dialog):</li> </ul> <pre><code>This change was integrated while the main issue was targeted to 'N'. The main issue has been reset to fixed in 'N+1', this backport issue has been reset to fix in 'na' and closed as Not An Issue to avoid confusion.</code></pre> <ul> <li>Change the <span class="jbs-field">Fix Version/s</span> from ‘N+1’ to ‘na’.</li> <li>Close the <em>backport</em> issue as <span class="jbs-value">Not an Issue</span>. Note: <span class="jbs-value">Closed</span>, <strong>not</strong> <span class="jbs-value">Resolved</span></li> </ul> <p>Even if you intend to backport the issue from ‘N+1’ to ‘N’ you shouldn’t reuse this backport issue. The existing (bad) push notification comment and the later to be added correct push notification comment will look very similar and it’s just a disaster waiting to happen to deliberately add these to the same issue.</p> </li> <li> <p>Clean up the <em>main</em> issue</p> <ul> <li>Copy the push notification comment from the <em>backport</em> issue to the <em>main</em> issue, e.g.:</li> </ul> <pre><code>Changeset: 12345678 Author: Duke <duke@openjdk.org> Date: 2020-10-23 15:37:46 +0000 URL: https://git.openjdk.org/jdk/commit/12345678</code></pre> <ul> <li>Add a comment like the following to the <em>main</em> issue:</li> </ul> <pre><code>This change was integrated to 'N+1' while this main issue was targeted to 'N'. This issue has been reset to fixed in 'N+1' and the Robo Duke entry was copied here.</code></pre> <ul> <li>Reset the <em>main</em> issue <span class="jbs-field">Fix Version/s</span> from ‘N’ to ‘N+1’.</li> <li>Resolve the <em>main</em> issue as <span class="jbs-value">Fixed</span> in build “team” or in build “master” depending on where the fix was integrated - or to an actual build number if the change has already made it to a promoted build (look in the <em>backport</em> issue if you are unsure). Integrations to ‘openjdk/jdk’ are fixed in build “master” and integrations to other Project repositories are fixed in build “team”.</li> </ul> </li> </ol> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="release-notes">Release Notes</h1> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://www.oracle.com/java/technologies/javase/jdk-relnotes-index.html"> JDK Release Notes</a></li> <li><a href="#release-note">release-note label description</a></li> <li><a href="https://spec.commonmark.org/current/">CommonMark Spec</a></li> <li><a href="https://spec.commonmark.org/dingus/">dingus</a></li> </ul> </div> <p>Release notes for a product such as the JDK are part of the release deliverables providing a way to highlight information about a fix, such as when it may have changed behavior, or when it’s decided not to fix something. While what should go into a release note isn’t something that can be precisely defined, it should describe changes that are important for a user to take into account when they are upgrading to the specific version. While release notes should not duplicate information in other documents, they can serve to highlight that a change has been made.</p> <p>Release notes are associated with a JBS issue that has been fixed (or in some cases not been fixed) in a release and are generated with each build of a release. Any note should be considered as an integral part of the fix process, rather than waiting until the end of the release to determine what to write. In OpenJDK, release notes are currently being generated for the JDK and JDK Updates Projects.</p> <h2 id="writing-a-release-note">Writing a release note</h2> <p>Writing the release note is the responsibility of the engineer who owns the issue. The note should be generated before the fix is reviewed, or in the case of known issues, when it’s determined that a fix won’t be possible in the release the issue was found in.</p> <p>When writing a release note, be prepared for rather picky review comments about grammar, typos, and wording. This is for the sake of the Java community as a whole, as the language of the release note sets the tone for many blogs and news articles. For a widely used product like the JDK, the release notes are often copied verbatim (including typos) and published to highlight news in the release. This means that we need to take extra care to make sure the text in the release note is correct and follows a similar style.</p> <p>The release note itself is written in a <a href="#jbs---jdk-bug-system">JBS</a> sub-task of the issue that is used to integrate the change. There are a few steps to follow for the release note to find its way from JBS to the actual release note document.</p> <ol> <li> <p>Create a sub-task (More → Create Sub-Task) for the issue that requires a release note - the main issue, that is, the JBS issue that is used to integrate the original change, <strong>not</strong> for backports or the CSR (if there is one).</p> </li> <li> <p>For the newly created sub-task, follow these steps:</p> <ul> <li>While the <span class="jbs-field">Priority</span> of the sub-task is set by default to be the same as the priority of the issue itself, it can be changed to adjust in what order the release note is listed compared to other release notes in the same build or release note section.</li> <li>Set the <span class="jbs-field">Assignee</span> to the same person who owns the main issue.</li> <li>The <span class="jbs-field">Summary</span> should be a one sentence synopsis that is informative (and concise) enough to attract the attention of users, developers, and maintainers who might be impacted by the change. It should succinctly describe what has actually changed, not be the original bug title, nor describe the problem that was being solved. It should read well as a sub-section heading in a document.</li> <li>Prefix the <span class="jbs-field">Summary</span> with “Release Note:”.</li> <li>Enter the text of the release note in the <span class="jbs-field">Description</span> field using markdown formatting, following the <a href="https://spec.commonmark.org/current/">CommonMark specification</a>. While the markdown won’t be rendered in JBS, you can use <a href="https://spec.commonmark.org/dingus/">dingus</a> to see what the release note will look like. Note that <a href="https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-tables"> Github style ascii table formatting</a> is supported but will not display correctly in the dingus page. For more information see <a href="#general-conventions-for-release-notes">General Conventions for Release Notes</a> below.</li> <li>Set <span class="jbs-field">Component/s</span> and <span class="jbs-field">Subcomponent</span> to the same values as the original bug.</li> <li>Set <span class="jbs-field">Affects Version/s</span> to the release versions for which the release note should be published.</li> <li>Add the <span class="jbs-label">release-note</span> label. This is required for the release note to be included in the release notes.</li> <li>Add the proper <span class="jbs-label">RN-</span>label if applicable to indicate what section of the release notes it should be included in (see <a href="#rn-labels">RN-labels</a> below).</li> <li>Set the <span class="jbs-field">Fix Version/s</span> to the same value that the main issue - in almost all cases this will be the version of mainline.</li> </ul> </li> <li> <p>Have the release note ready to be reviewed at the same time as the code is reviewed. If it’s later determined that a release note is necessary, then go back to the same engineers who reviewed the fix to review the release note. Special care should be taken when writing a release note that will cover changes related to a vulnerability fix in order to avoid describing technical details of how it could have been exploited.</p> </li> <li> <p>When you are done, <em>Resolve</em> the release note sub-task as <code>Delivered</code>. Only release notes where the sub-task has been resolved as <code>Delivered</code> is considered to be part of the EA/GA release notes. To avoid mixing up the release notes with the code fixes that have gone into a particular release or build, we don’t use <code>Resolved/Fixed</code>.</p> </li> </ol> <p>If you see an issue you feel should have a release note but you are not the assignee of the bug, then add the label <span class="jbs-label">release-note=yes</span> to the main bug (not on a backport nor a sub-task). This acts as a flag to make sure that the release note is considered. This can be done even with fixes that have been shipped already if it’s noticed that there is confusion around the change. If, after discussion, it’s decided that a release note isn’t required either remove the label, or change it to <span class="jbs-label">release-note=no</span> if it makes sense to have a clear indication that a release note isn’t required for the fix. The label <span class="jbs-label">release-note=yes</span> can be removed once the release note sub-task has been created.</p> <p>For examples of well written release note issues in JBS, see <a href="https://bugs.openjdk.org/browse/JDK-8276929">JDK-8276929</a> or <a href="https://bugs.openjdk.org/browse/JDK-8278458">JDK-8278458</a>.</p> <h2 id="general-conventions-for-release-notes">General conventions for release notes</h2> <p>The following are general practices that should be followed when creating release notes.</p> <ul> <li> <p>Release notes should be no longer than 2-3 paragraphs.</p> </li> <li> <p>Don’t repeat information that will be included in updates to the docs, keep it to a high level summary or key changes.</p> </li> <li> <p>Note that where the changes are more fully documented in the JDK documentation, then refer to that document for details. When covering a change in behavior provide some idea to what can be done if a developer or user encounters problems from the change.</p> </li> <li> <p>Don’t include graphics etc. Refer to the main docs if there are more details that need explaining.</p> </li> <li> <p>Don’t include your name or affiliation, make sure however, you are the assignee of the release note sub-task.</p> </li> <li> <p>If you have a < in the <span class="jbs-field">Summary</span> then use <code>&lt;</code>. For <’s in the <span class="jbs-field">Description</span> surround them by back-ticks.</p> </li> <li> <p>Avoid using Latin and abbreviations in the release note.</p> <ul> <li>Use “also known as” instead of “aka”</li> <li>Use “that is” or “to be specific” instead of “i.e.”</li> <li>Use “for example” instead of “e.g.”</li> </ul> </li> <li> <p>The <span class="jbs-field">Summary</span> should be in title case instead of sentence case.</p> <ul> <li>Example: Decode Error with Tomcat Version 7.x</li> </ul> </li> <li> <p>The <span class="jbs-field">Description</span> should be standardized to follow this pattern:</p> <ul> <li>Sentence stating the change that was made</li> <li>Background info/context</li> <li>Example: A new system property, <code>jdk.disableLastUsageTracking</code>, has been introduced to disable JRE last usage tracking for a running VM.</li> </ul> </li> </ul> <h2 id="advanced-options">Advanced options</h2> <ul> <li>JEP release notes <ul> <li><span class="jbs-field">Summary</span> - If the change is an actual JEP, use the JEP title.</li> <li><span class="jbs-field">Description</span> - the JEP Summary text have already been heavily reviewed and also approved by the Project lead. It should be the first sentence in the release note description. That would be analogous to the “change that was made” sentence in other release note descriptions. The remaining text would be composed of the background info from the JEP.</li> <li><span class="jbs-field">Description</span> - The JEP release note description should contain the link to the JEP.</li> </ul> </li> <li>Single release note for multiple changes <ul> <li>A link to the parent issue that the note is a sub-task of, will be placed alongside the summary in the release notes. If note relates to additional changes, then add them as <span class="jbs-field">Relates</span> links to the note and add the label <span class="jbs-label">RN-MultipleLinks</span> - see <a href="https://bugs.openjdk.org/browse/JDK-8284975">JDK-8284975</a> as an example.</li> </ul> </li> <li>Multiple release notes for the same change <ul> <li>If more than one release note is required for the same set of fixes, then open additional sub-tasks with the same <span class="jbs-field">Affects Version</span> - see <a href="https://bugs.openjdk.org/browse/JDK-8073861">JDK-8073861</a> as an example.</li> </ul> </li> <li>Release notes across backports <ul> <li>If an issue is backported to earlier releases the same note will be used - just add the new release version in the <span class="jbs-field">Affects Version</span> field of the release note.</li> <li>Where a different release note is required, then create a separate note with the <span class="jbs-field">Affects Version</span> for the new release - see <a href="https://bugs.openjdk.org/browse/JDK-8308194">JDK-8308194</a> and <a href="https://bugs.openjdk.org/browse/JDK-8322473">JDK-8322473</a> for an example.</li> </ul> </li> </ul> <h2 id="rn-labels">RN-labels</h2> <p>Unless labeled otherwise it will be assumed that the release note documents a change in behavior (will have likely required a CSR) or other item which should be included in the release notes. If the note covers a more specific type of change, then one of the following labels can be included (notes of a similar type will be listed together).</p> <dl> <dt><span id="RN-NewFeature"><span class="jbs-label">RN-NewFeature</span></span></dt> <dd>A new feature or enhancement in the release. The <span class="jbs-field">Summary</span> must be the item/API or new functionality. The <span class="jbs-field">Description</span> must contain the name of the new feature, its intended function, and how a user can utilize it. Example: <a href="https://bugs.openjdk.org/browse/JDK-8315443">JDK-8315443</a></dd> <dt><span id="RN-IssueFixed"><span class="jbs-label">RN-IssueFixed</span></span></dt> <dd>A significant issue which has been fixed. This would normally be a regression or an issue which was unknowingly released in a new feature. The <span class="jbs-field">Summary</span> must be a summary of the error that was fixed. The <span class="jbs-field">Description</span> must contain a statement about what was fixed, how the fix effects the user, and any special conditions that a user should be aware of regarding the fix. Example: <a href="https://bugs.openjdk.org/browse/JDK-8184172">JDK-8184172</a></dd> <dt><span id="RN-KnownIssue"><span class="jbs-label">RN-KnownIssue</span></span></dt> <dd>An issue that wasn’t possible to fix by the time the release was GA’d. The <span class="jbs-field">Summary</span> must be a summary of the error that the user sees. The <span class="jbs-field">Description</span> must contain details about the error, how it effects the user, and workarounds if any exist. Example: <a href="https://bugs.openjdk.org/browse/JDK-8191040">JDK-8191040</a></dd> <dt><span id="RN-Removed"><span class="jbs-label">RN-Removed</span></span></dt> <dd>Only for major releases. The release note covers an API, feature, tool etc. which has been removed from the JDK. The <span class="jbs-field">Summary</span> must be of the form “Removal of” Item/API. The <span class="jbs-field">Description</span> must contain the list or name of the removed items/API with (optional) the reason for its removal. Include any special conditions that a user should be aware of regarding the removal. Example: <a href="https://bugs.openjdk.org/browse/JDK-8185066">JDK-8185066</a></dd> <dt><span id="RN-Deprecated"><span class="jbs-label">RN-Deprecated</span></span></dt> <dd>Only for major releases. The release notes cover an API, feature, tool etc. that has been marked as deprecated in the release. The <span class="jbs-field">Summary</span> must be of the form “Deprecated” Item/API. The <span class="jbs-field">Description</span> must contain the name of the item that has been deprecated, the reason for its deprecation, and (optional) any special conditions that a user should be aware of regarding the possible future removal. Example: <a href="https://bugs.openjdk.org/browse/JDK-8179909">JDK-8179909</a></dd> <dt><span id="RN-Important"><span class="jbs-label">RN-Important</span></span></dt> <dd>Used to indicate that the release note should be highlighted in some fashion, such as listing it at the beginning of the release notes.</dd> <dt><span id="RN-distro"><span class="jbs-label">RN-</span><em>(distro)</em></span></dt> <dd>Used to indicate that the release note is only relevant for a specific JDK distribution. E.g. <span class="label">RN-Oracle</span></dd> <dt><span id="RN-MultipleLinks"><span class="jbs-label">RN-MultipleLinks</span></span></dt> <dd>Used to indicate that the release note should refer to multiple changes - see <a href="#advanced-options">Advanced options</a> section.</dd> <dt><span id="RN-Change"><span class="jbs-label"><del>RN-Change</del></span></span></dt> <dd>Deprecated. This is the default and no label is needed to indicate this.</dd> </dl> <h2 id="querying-the-release-notes">Querying the release notes</h2> <p>The Release Notes for a particular release can be found using the JBS query</p> <pre><code>affectedversion = <version> and type = sub-task and labels = release-note</code></pre> <p>where <code><version></code> is the appropriate release value, e.g. 17.</p> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="the-jdk-release-process">The JDK Release Process</h1> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://openjdk.org/jeps/3">JEP 3: JDK Release Process</a></li> </ul> </div> <p>The JDK Project has a well defined release process. <a href="https://openjdk.org/jeps/3">JEP 3</a> describes this process in detail. This section intends to clarify some topics that often cause questions.</p> <h2 id="release-cycle">Release cycle</h2> <p>The release cycle starts when development of a new release begins, and ends when that release is delivered to the public. The current release cadence is six months. This means that every six months we start development of a new release, and every six months a new release is delivered. However, this doesn’t mean that each release cycle is six months. As described below, the total development time for a release (the release cycle) is actually nine months. Obviously this in turn doesn’t mean that all features are developed in nine months. Most features are developed for a much longer time than that, and goes through long time development in other Project repositories, and through a series of preview and experimental stages. But any feature that is to be included in a specific release has a specific window of nine months to integrate the code into mainline and fix all the remaining bugs.</p> <p>It may be tempting to integrate a new feature near the end of a release cycle, to get more time to fix all those last bugs before integration. Please don’t. If you are getting close to the end of a release and you still just have one more bug to fix, please defer your feature to the next release. It’s only six months out. Not only will this vouch for your new feature to be more stable on release, you will also help keeping the JDK as a whole more stable by allowing others to find and fix bugs in their new code that might come as a result of your changes.</p> <p>Integrating early in a release is preferable, but all new features can’t be integrated at the same time. If many large changes enters the repository at the same time it will be more difficult to determine which change that caused all the new bugs. If you’re about to integrate a larger change you must therefore communicate this on the relevant <a href="#mailing-lists">mailing lists</a> to synchronize with other Projects that may also be planning to integrate something soon.</p> <h2 id="milestones-and-phases">Milestones and phases</h2> <p>Throughout the release there are a number of milestones and phases that define where in the release cycle we are.</p> <dl> <dt><span id="release-start"><strong>The start of a release</strong></span></dt> <dd>Since development is always ongoing in the master branch of the mainline repository (<a href="https://github.com/openjdk/jdk">openjdk/jdk</a>), the start of a new release can be said to be when the former release is branched for stabilization. After the start of the release follows six months of development to implement and integrate all the cool stuff that will go into the next release. After these six months ramp down begins.</dd> <dt><span id="rdp1"><strong>Ramp Down Phase 1 (RDP1)</strong></span></dt> <dd>The ramp down of a release starts with a new branch being created (the stabilization branch) from the master branch in the mainline repository. During the ramp down of a release we focus on bug fixing and stabilization in order to get the JDK ready for release. In RDP1 you may continue to fix P1-P3 product bugs (and some other issues) in the stabilization branch. For detailed information on what can be fixed when, see <a href="#push-or-defer-during-ramp-down">Push or defer during ramp down</a> below. The start of RDP1 is essentially the deadline for integrating JEPs and enhancements into a particular release.</dd> <dt><span id="atr"><strong>All Tests Run (ATR)</strong></span></dt> <dd>ATR is not a milestone described in JEP 3, but it’s still a concept that might be mentioned in discussions on this topic and is therefore good to know about. ATR (a.k.a. ATR Start) is the start of an approximately six week long test period where all tests in the test plan for the given release is ran. ATR usually starts at the same time as RDP1.</dd> <dt><span id="rdp2"><strong>Ramp Down Phase 2 (RPD2)</strong></span></dt> <dd>In RDP2 the bar is higher to get changes into the release. For product bugs, only P1:s and P2:s are supposed to be fixed here, and to do so an approval is needed. See the <a href="https://openjdk.org/jeps/3#Fix-Request-Process">Fix-Request Process</a> for details on how to obtain one. All other product bugs should be deferred. See <a href="#push-or-defer-during-ramp-down">Push or defer during ramp down</a> below for more details.</dd> <dt><span id="rc"><strong>Release Candidate (RC)</strong></span></dt> <dd>Towards the end of the release cycle, when there are no more open product bugs targeted to the release, a stable build is selected to be the release candidate. This build will go through additional testing and if no more issues are found it will be the build released. If new bugs are found these are investigated and hopefully fixed, and a new build becomes the release candidate. The RC phase has a few milestones with a deadline for finding a candidate build, and another for making sure the build is ready to go live.</dd> <dt><span id="ga"><strong>General Availability (GA)</strong></span></dt> <dd>This is the end of the release cycle. The last release candidate build is made available to the public.</dd> </dl> <h3 id="push-or-defer-during-ramp-down">Push or defer during ramp down</h3> <p><a href="https://openjdk.org/jeps/3">JEP 3</a> contains the exact definitions for what can be done when. This is a visualization of those definitions that may or may not clarify things.</p> <div class="figure"><img src="push-defer.png" alt="" /> <p class="caption">Push and defer guidelines during ramp down</p> </div> <h3 id="deferring-p1-and-p2-bugs">Deferring P1 and P2 bugs</h3> <p>Even though there’s nothing explicitly written in the process about deferring P1 and P2 bugs during the initial development phase, the assumption is that these aren’t deferred unless time runs out at the end of the release cycle.</p> <p>Please note that the priority of a bug doesn’t change just because you want to get your fix in late in the release, or if you want to be able to defer it. The priority is based on the severity of the bug and if it was deemed to be a P2 before, you better have a really good explanation to why that conveniently has changed by the end of the release. Being hard to fix is <strong>not</strong> a reason to lower the priority of a bug.</p> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="project-maintenance">Project Maintenance</h1> <p>Many <a href="https://openjdk.org/bylaws#project">OpenJDK Projects</a> build on top of the JDK source code for instance to produce new language features, like Projects <a href="https://openjdk.org/projects/amber/">Amber</a> and <a href="https://openjdk.org/projects/valhalla/">Valhalla</a>. When doing this there are a number of common workflows that are dealt with by most Project maintainers. For instance, updating the codebase (merging) to bring in the latest changes from the upstream JDK Project.</p> <h2 id="merging-jdk-mainline-into-a-project-repository">Merging JDK mainline into a Project repository</h2> <p>Merging changes from one git repository to another is basically the same thing as getting your own changes merged into the Project repository, with the slight twist that you don’t write all the changes yourself, you just pull them from somewhere else.</p> <p>In this example we’ll use a separate clone of the Project repository to perform the merge in. This can be done using branches as well, but let’s keep it simple for now.</p> <h3 id="init---done-once">Init - done once</h3> <p>First set up your personal fork of the Project repository, in this example called <code>my-project</code>. If you already are a <a href="https://openjdk.org/bylaws#contributor">Contributor</a> to the <a href="https://openjdk.org/bylaws#project">Project</a> you most likely have this set up. If not, see <a href="#cloning-the-jdk">Cloning the JDK</a> for details on how to do that.</p> <pre class="shell"><code>git clone git@github.com:OpenDuke/my-project.git project-merge cd project-merge git remote add upstream git@github.com:openjdk/my-project.git git remote add mainline git@github.com:openjdk/jdk.git</code></pre> <p>We clone the personal fork (in this case we clone OpenDuke’s personal fork) into a local directory, here called <code>project-merge</code>. We then set up two remotes, <code>upstream</code> and <code>mainline</code>.</p> <h3 id="performing-the-merge">Performing the merge</h3> <p>The clone we set up above is used each time you want to bring changes from mainline in to your <a href="https://openjdk.org/bylaws#project">Project</a>. This is done by first pulling the changes from mainline and then pushing to your personal fork. A regular PR will then be created which you can integrate into your main Project repository. It sounds easy, and it is, but there are a few details below to keep in mind.</p> <pre class="shell"><code>cd project-merge git pull upstream master git push git switch -c Merge_mainline git fetch mainline</code></pre> <p>We start by updating the local fork with the latest changes from the main Project repository. Note that we then create a new branch “<code>Merge_mainline</code>” in which the merge will happen. Finally we fetch all new changes from mainline.</p> <p>Merging from what ever is latest isn’t usually a good idea, mainline code is not “clean” for any given commit. Merging JDK tags ensures you have a known quality, those tagged commits are known to compile and pass tests. Therefore, next we check which tags have not been merged yet.</p> <pre class="shell"><code>git tag -l "jdk-*" --no-merged</code></pre> <p>Or if you just want to see the latest tag you haven’t merged,</p> <pre class="shell"><code>git tag -l "jdk-*" --no-merged | tail --lines 1</code></pre> <p>Before merging, you may want to check what’s incoming, to get an idea of the size of the merge and look for any incoming changes that you suspect may cause issues.</p> <pre class="shell"><code>git log --topo-order --pretty=oneline --reverse ..$TAG</code></pre> <p>And finally we initiate the actual merge.</p> <pre class="shell"><code>git merge $TAG</code></pre> <p>The commands above will likely run without a hitch up until the final <code>git merge</code>. This is where you need to combine the changes that were made in mainline with the changes that have been made in your Project repository. If there are no conflicts you’re in luck, then the merge will be completely automated and you will end up with a committed merge. If there are conflicts however you’ll need to manually go through the files where the conflicts are and make sure you select the correct version for each change. Using <code>git status</code> you can see what files that need to be merged. Depending on how much code your <a href="https://openjdk.org/bylaws#project">Project</a> has touched, this can be quite a bit of work.</p> <p>For complicated merges, see <a href="#sharing-the-work">Sharing the work</a> below.</p> <h3 id="test-before-integration">Test before integration</h3> <p>Regardless of if you encountered conflicts or not, you should always build and test your merge before integrating it to your Project repository. Testing needs to be done even when there are no textual conflicts as changes like for instance a rename can result in a compile or test error without any conflict. One could argue that <code>git merge --no-commit</code> could be used and have logical errors fixed in the merge commit. However, a subsequent “Fix logical merge errors” commit, is in fact more useful, as it clearly shows the Project specific adjustments needed for incoming changes.</p> <p>It’s always okay to have further commits to clean up after a merge. Hiding a large amount of reworking Project code to fit with upstream changes in a single merge commit will make it hard for further errors post integration to be identified.</p> <h3 id="the-commit-push-and-pr">The commit, push, and PR</h3> <p>Once you have a working version of your merged code you’re ready to create the merge commit and push. Please note that <code>git commit</code> is only needed if there were conflicts. If the changes were successfully merged by <code>git merge</code>, you already have a committed merge.</p> <pre><code>git commit -m "Merge" git push --set-upstream origin Merge_mainline</code></pre> <p>Now it’s time to create the PR on <a href="https://github.com">GitHub</a>. Just opening the PR page in your browser will most often be enough to see a message about new code that was pushed to your personal fork. Click the button to create the PR.</p> <p>Make sure the PR title starts with “Merge”. You may have noticed that when you integrate a “normal” PR into an OpenJDK repository, all commits that have been done in that PR will be squashed into a single commit. For normal changes this is a good thing as each PR normally corresponds to a single JBS issue, but for a merge it would be highly undesirable to squash all the different commits that you pull in from mainline. A PR with a title that starts with “Merge” won’t be squashed. That means that all the changes that you brought over will remain separate changes.</p> <p>It’s always a good idea to also include what was merged in the title of the PR. If you for instance is pulling in JDK mainline into your Project repository it’s likely (because it’s in general a good idea) that you choose some stable EA tag in mainline to merge. Your PR title could then be something like “Merge jdk-21+2”.</p> <p>Whether a merge requires a review or not is up to your Project lead to decide. Many <a href="https://openjdk.org/bylaws#project">Projects</a> don’t require this so the GitHub bots will allow you to integrate the merge as soon as the <a href="#github-actions">GHA</a>s are done. (They actually allow you to integrate even before the GHAs are done, but that’s in general not a good idea.)</p> <p>Once the PR has been integrated, you can clean up your fork and its clone in preparation for the next merge.</p> <pre><code>git switch master git branch -d Merge_mainline git push -d origin Merge_mainline</code></pre> <p>These commands will remove the temporary branch that we created to perform the merge. There’s a button in the GitHub GUI to delete the branch after you have integrated the PR. This can be used instead of the last of the three commands above (<code>git push -d...</code>).</p> <h3 id="sharing-the-work">Sharing the work</h3> <p>When conflicts take place in areas requiring specialized knowledge you may need help from other <a href="https://openjdk.org/bylaws#contributor">Contributors</a>. Backing up the original conflicts will help if you find yourself “in too deep”, and need assistance from other <a href="https://openjdk.org/bylaws#contributor">Contributors</a>. You can add and later remove these backups, along with a readme describing the merge status, to the actual merge branch to aid communication (i.e. you may not be able to compile certain components).</p> <p>Something like the following shell one-liner can be used to perform the backup.</p> <pre class="shell"><code>git status | grep "both modified:" | while read B M FILE; do cp -v $FILE $DEST ; done</code></pre> <p>Below are two different methods of collaborating on a merge described. Please note that extra commits are fine. The merge PR itself will describe any special actions that were taken in case further failures turn up after merge integration. Ultimately these commits will be squashed when integrating the project back into mainline.</p> <h4 id="parking-a-merge-with-conflicts-in-place">1. Parking a merge with conflicts in place</h4> <p>“Park” the conflicts, unresolved, in a personal fork, and let others do the further work (by sending you a patch, or opening your personal fork up to push from other <a href="https://openjdk.org/bylaws#contributor">Contributors</a>). Do this by keeping a list of unresolved conflicts (perhaps checking in said list to describe the merge state), and then marking them as resolved in git, committing, and pushing them to your personal fork. E.g. <code>git add $UNRESOLVED_FILES; git commit; git push</code></p> <p><strong>Pros:</strong> All unresolved conflicts are stated and can be worked on by multiple parties, all at once.</p> <p><strong>Cons:</strong> Broken branch in terms of compile and test, may require temporary workaround patches to be passed around to complete work on specific unresolved components.</p> <h4 id="incremental-merging">2. Incremental merging</h4> <p>An alternative to parking a merge with conflicts in place, is to incrementally merge up to the troublesome point. For example:</p> <ul> <li>Perform the initial merge: <code>git merge $TAG</code></li> <li>Find yourself in trouble, identify which change is causing the issue.</li> <li>Abort: <code>git merge --abort</code></li> <li>Find the troublesome change: <code>git log --topo-order --pretty=oneline --reverse $(current_branch)..$TAG</code></li> <li>Merge up to the previous change, commit and integrate.</li> <li>Ask others to continue the merge from the troubled change forward, how far forward is up you of course, either just that troublesome change, or the rest of the merge up to the $TAG.</li> <li>Rinse and repeat: There may appear further conflicts requiring other <a href="https://openjdk.org/bylaws#contributor">Contributors’</a> help.</li> </ul> <p><strong>Pros:</strong> All commits in the merge branch compile and test, you always have a working branch.</p> <p><strong>Cons:</strong> There is an unknown extra amount of merge work, multiple iterations create more work. For instance you may find yourself resolving the same files multiple times (e.g. back-out commits).</p> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="hotspot-development">HotSpot Development</h1> <p>See <a href="#working-with-pull-requests">Working With Pull Requests</a> for generic guidance and requirements around integrating changes. For the HotSpot codebase there are a few additional requirements:</p> <ul> <li>Your change must have been approved by two reviewers out of which at least one is also a <a href="https://openjdk.org/bylaws#reviewer">Reviewer</a></li> <li>Your change must have passed through HotSpot tier 1 testing with zero failures (See tier1 definition in <code>test/hotspot/jtreg/TEST.groups</code>.)</li> </ul> <h2 id="logging">Logging</h2> <div class="box"> <p><span class="boxheader">Quick Links</span></p> <ul> <li><a href="https://openjdk.org/jeps/158">JEP 158: Unified JVM Logging</a></li> </ul> </div> <p>While developing your fix, you might want your code to output some diagnostic information. You might even want to leave some logging in the code you check in, to facilitate future diagnostics. The appropriate way to print logging output from HotSpot is through the <a href="https://openjdk.org/jeps/158">Unified Logging Framework (JEP 158)</a>. It gives you a lot of nice features and enables common command-line options for all logging.</p> <p>A basic log message can be output like this:</p> <div class="sourceCode" id="cb47"> <pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a>log_info<span class="op">(</span>gc<span class="op">,</span> marking<span class="op">)(</span><span class="st">"Mark Stack Usage: "</span> SIZE_FORMAT <span class="st">"M"</span><span class="op">,</span> _mark_stack_usage <span class="op">/</span> M<span class="op">);</span></span></code></pre></div> <p>Where ‘gc’ and ‘marking’ are tags, and ‘info’ is the log level. Tags associate log messages with certain subsystems or features and the log level determines the importance and verbosity of the message. The most verbose output is trace, and the least is error. The full list of tags and levels are available via <code>-Xlog:help</code>.</p> <p>The basic log API looks as follows:</p> <div class="sourceCode" id="cb48"> <pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb48-1"><a href="#cb48-1" aria-hidden="true" tabindex="-1"></a><span class="va">log_</span><span class="op"><</span>level<span class="op">>(</span>Tag1<span class="op">[,...])(</span>fmtstr<span class="op">,</span> <span class="op">...)</span></span></code></pre></div> <p>Sometimes single line printf-style logging isn’t enough. For example, it can be useful to group several log lines together or to use HotSpot’s outputstream API. UL supports both of these use cases using <code>LogMessage</code> and <code>LogStream</code>, respectively.</p> <div class="sourceCode" id="cb49"> <pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb49-1"><a href="#cb49-1" aria-hidden="true" tabindex="-1"></a>LogMessage<span class="op">(</span>gc<span class="op">,</span> marking<span class="op">)</span> lm<span class="op">;</span></span> <span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>lm<span class="op">.</span>is_info<span class="op">())</span> <span class="op">{</span></span> <span id="cb49-3"><a href="#cb49-3" aria-hidden="true" tabindex="-1"></a> lm<span class="op">.</span>info<span class="op">(</span><span class="st">"We are guaranteed to be"</span><span class="op">);</span></span> <span id="cb49-4"><a href="#cb49-4" aria-hidden="true" tabindex="-1"></a> lm<span class="op">.</span>info<span class="op">(</span><span class="st">" grouped together"</span><span class="op">);</span></span> <span id="cb49-5"><a href="#cb49-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> <p><code>LogMessage</code> will submit its output when it goes out of scope.</p> <p><code>LogStream</code> is typically used when a single printf-style format string becomes unwieldy.</p> <div class="sourceCode" id="cb50"> <pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb50-1"><a href="#cb50-1" aria-hidden="true" tabindex="-1"></a>LogStream st<span class="op">(</span>Log<span class="op">(</span>gc<span class="op">,</span> marking<span class="op">)::</span>info<span class="op">());</span></span> <span id="cb50-2"><a href="#cb50-2" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>st<span class="op">.</span>is_enabled<span class="op">())</span> <span class="op">{</span></span> <span id="cb50-3"><a href="#cb50-3" aria-hidden="true" tabindex="-1"></a> <span class="co">// Print without newline</span></span> <span id="cb50-4"><a href="#cb50-4" aria-hidden="true" tabindex="-1"></a> st<span class="op">.</span>print<span class="op">(</span><span class="st">"I'm printing a lot of </span><span class="sc">%s</span><span class="st"> "</span><span class="op">,</span> <span class="st">"arguments"</span><span class="op">);</span></span> <span id="cb50-5"><a href="#cb50-5" aria-hidden="true" tabindex="-1"></a> st<span class="op">.</span>print<span class="op">(</span><span class="st">"With a lot of extra info </span><span class="sc">%d</span><span class="st"> "</span><span class="op">,</span> <span class="dv">3</span><span class="op">);</span></span> <span id="cb50-6"><a href="#cb50-6" aria-hidden="true" tabindex="-1"></a> <span class="co">// Print with newline (cr stands for carriage return)</span></span> <span id="cb50-7"><a href="#cb50-7" aria-hidden="true" tabindex="-1"></a> st<span class="op">.</span>print_cr<span class="op">(</span><span class="st">"and so it's useful to use a stream"</span><span class="op">);</span></span> <span id="cb50-8"><a href="#cb50-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> <p>If you need to print multiple lines grouped together with complex formatting requirements then <code>NonInterleavingLogStream</code> is probably what you want.</p> <div class="sourceCode" id="cb51"> <pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb51-1"><a href="#cb51-1" aria-hidden="true" tabindex="-1"></a>LogMessage<span class="op">(</span>gc<span class="op">)</span> lm<span class="op">;</span></span> <span id="cb51-2"><a href="#cb51-2" aria-hidden="true" tabindex="-1"></a>NonInterleavingLogStream st<span class="op">{</span>LogLevelType<span class="op">::</span>Info<span class="op">,</span> lm<span class="op">};</span></span> <span id="cb51-3"><a href="#cb51-3" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>st<span class="op">.</span>is_enabled<span class="op">())</span> <span class="op">{</span></span> <span id="cb51-4"><a href="#cb51-4" aria-hidden="true" tabindex="-1"></a> st<span class="op">.</span>print_cr<span class="op">(</span><span class="st">"Line one: </span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d</span><span class="st"> "</span><span class="op">,</span> <span class="dv">1</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">3</span><span class="op">);</span></span> <span id="cb51-5"><a href="#cb51-5" aria-hidden="true" tabindex="-1"></a> st<span class="op">.</span>print<span class="op">(</span><span class="st">"Line two: </span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d</span><span class="st">"</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> <span class="dv">5</span><span class="op">,</span> <span class="dv">6</span><span class="op">);</span></span> <span id="cb51-6"><a href="#cb51-6" aria-hidden="true" tabindex="-1"></a> st<span class="op">.</span>print_cr<span class="op">(</span><span class="st">" still line two: </span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d</span><span class="st">"</span><span class="op">,</span> <span class="dv">7</span><span class="op">,</span> <span class="dv">8</span><span class="op">,</span> <span class="dv">9</span><span class="op">);</span></span> <span id="cb51-7"><a href="#cb51-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> <h3 id="enabling-logging">Enabling logging</h3> <p>You enable logging in the JVM by using the <code>-Xlog</code> command line option specified. For example, the messages from the examples would be visible if the JVM were run with any of the following options:</p> <pre><code>-Xlog:gc+marking=info -Xlog:gc+marking -Xlog:gc*</code></pre> <p>You can have multiple <code>-Xlog</code> options, these are applied in an additive manner. Consider this example:</p> <pre><code>-Xlog:gc+marking=info:stdout -Xlog:alloc=warning:stderr -Xlog:breakpoint=error:breakpoint.txt:level</code></pre> <p>This specifies that:</p> <ol style="list-style-type: decimal"> <li>Log messages with info level and up, with tags gc and marking, to stdout.</li> <li>Log messages with warning level and up, with tag alloc, to stderr.</li> <li>Log messages with error level and up, with tag breakpoint, to file breakpoint.txt, with the decorator level.</li> </ol> <p>UL automatically applies a default argument of <code>-Xlog:all=warning:stdout:uptime,level,tags</code> when logging is enabled. This can be disabled by prepending <code>-Xlog:disable</code> to your arguments.</p> <pre><code>-Xlog:disable -Xlog:gc+marking=info -Xlog:alloc=warning</code></pre> <p>Starting the JVM with the option <code>-Xlog:help</code> outputs more information and more examples.</p> <p>A full description of the syntax of <code>-Xlog</code> is available in <a href="https://openjdk.org/jeps/158">JEP 158</a>.</p> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="code-owners">Code Owners</h1> <p>This list is intended to make it easier to identify which email list to include in code reviews when making changes in different areas. The list may also help when assigning bugs based on which code they are found in. Please note that some directories may have been created or removed between releases. The intention here is to include directories that exists in mainline, LTS releases and other releases (post JDK 9) commonly being updated.</p> <h2 id="area-mailing-lists">Area mailing lists</h2> <ul> <li>Generic JDK Development: <a href="https://mail.openjdk.org/mailman/listinfo/jdk-dev"><code>jdk-dev</code></a></li> <li>Build: <a href="https://mail.openjdk.org/mailman/listinfo/build-dev"><code>build-dev</code></a></li> <li>Client Libs: <a href="https://mail.openjdk.org/mailman/listinfo/client-libs-dev"><code>client-libs-dev</code></a></li> <li>Core Libs: <a href="https://mail.openjdk.org/mailman/listinfo/core-libs-dev"><code>core-libs-dev</code></a> <ul> <li>Net: <a href="https://mail.openjdk.org/mailman/listinfo/net-dev"><code>net-dev</code></a></li> <li>NIO: <a href="https://mail.openjdk.org/mailman/listinfo/nio-dev"><code>nio-dev</code></a></li> <li>I18n: <a href="https://mail.openjdk.org/mailman/listinfo/i18n-dev"><code>i18n-dev</code></a></li> </ul> </li> <li>HotSpot: <a href="https://mail.openjdk.org/mailman/listinfo/hotspot-dev"><code>hotspot-dev</code></a> <ul> <li>Compiler: <a href="https://mail.openjdk.org/mailman/listinfo/hotspot-compiler-dev"><code> hotspot-compiler-dev</code></a></li> <li>GC: <a href="https://mail.openjdk.org/mailman/listinfo/hotspot-gc-dev"><code>hotspot-gc-dev</code></a></li> <li>Runtime: <a href="https://mail.openjdk.org/mailman/listinfo/hotspot-runtime-dev"><code> hotspot-runtime-dev</code></a></li> <li>JFR: <a href="https://mail.openjdk.org/mailman/listinfo/hotspot-jfr-dev"><code>hotspot-jfr-dev</code></a></li> <li>Serviceability: <a href="https://mail.openjdk.org/mailman/listinfo/serviceability-dev"><code> serviceability-dev</code></a></li> </ul> </li> <li>Java Language (javac): <a href="https://mail.openjdk.org/mailman/listinfo/compiler-dev"><code>compiler-dev</code></a></li> <li>Security: <a href="https://mail.openjdk.org/mailman/listinfo/security-dev"><code>security-dev</code></a></li> <li>Tools <ul> <li>Javadoc: <a href="https://mail.openjdk.org/mailman/listinfo/javadoc-dev"><code>javadoc-dev</code></a></li> <li>JShell: <a href="https://mail.openjdk.org/mailman/listinfo/kulla-dev"><code>kulla-dev</code></a></li> <li>Nashorn: <a href="https://mail.openjdk.org/mailman/listinfo/nashorn-dev"><code>nashorn-dev</code></a></li> </ul> </li> </ul> <h2 id="directory-to-area-mapping">Directory to area mapping</h2> <ul> <li><a href="https://github.com/openjdk/jdk/tree/master/.jcheck">.jcheck</a> - Build</li> <li><a href="https://github.com/openjdk/jdk/tree/master/bin">bin</a> - Build</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/demo">demo</a> - Client Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/doc">doc</a></li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot">hotspot</a> <ul> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/cpu">cpu</a> - Compiler, Runtime</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/os">os</a> - Runtime</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/os_cpu">os_cpu</a> - Compiler</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share">share</a> <ul> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/adlc"> adlc</a> - Compiler</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/asm">asm</a> - Runtime</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/c1">c1</a> - Compiler</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/cds">cds</a> - Runtime</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/ci">ci</a> - Compiler</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/classfile"> classfile</a> - Runtime</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/code"> code</a> - Compiler</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/compiler"> compiler</a> - Compiler</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/gc">gc</a> - GC</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/include"> include</a> - HotSpot</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/interpreter"> interpreter</a> - Runtime</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/jfr">jfr</a> - JFR</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/jvmci"> jvmci</a> - Compiler</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/libadt"> libadt</a> - Compiler</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/logging"> logging</a> - Runtime</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/memory"> memory</a> - GC, Runtime</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/metaprogramming"> metaprogramming</a> - HotSpot</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/nmt">nmt</a> - Runtime</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/oops"> oops</a> - GC, Runtime</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/opto"> opto</a> - Compiler</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/precompiled"> precompiled</a> - HotSpot</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/prims"> prims</a> - Runtime, Serviceability</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/runtime"> runtime</a> - Runtime</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/sanitizers"> sanitizers</a> - Runtime</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/services"> services</a> - Runtime</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/hotspot/share/utilities"> utilities</a> - GC, Runtime</li> </ul> </li> </ul> </li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base">java.base</a> <ul> <li>Core Libs should almost always be included but Java Language, HotSpot, Security and/or I18n may also be involved.</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/aix/classes">aix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/linux/classes"> linux</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/macosx/classes"> macosx</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/classes"> share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/classes"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/classes"> windows</a>]/classes <ul> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/com/sun/crypto"> com/sun/crypto</a> - Security</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/com/sun/security"> com/sun/security</a> - Security</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/javax/crypto"> crypto</a> - Security</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/aix/classes/jdk/internal">aix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/linux/classes/jdk/internal"> linux</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/macosx/classes/jdk/internal"> macosx</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/classes/jdk/internal"> share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/classes/jdk/internal"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/classes/jdk/internal"> windows</a>]/internal <ul> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/access"> access</a> - Core Libs, Security</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/event"> event</a> - JFR</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/foreign"> foreign</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/icu"> icu</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/io"> io</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/javac"> javac</a> - Java Language (javac)</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/jimage"> jimage</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/jmod"> jmod</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/jrtfs"> jrtfs</a> - Core Libs</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/aix/classes/jdk/internal/loader">aix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/macosx/classes/jdk/internal/loader"> macosx</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/classes/jdk/internal/loader"> share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/classes/jdk/internal/loader"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/classes/jdk/internal/loader"> windows</a>]/loader - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/logger"> logger</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/math"> math</a> - Core Libs</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/share/classes/jdk/internal/misc">share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/classes/jdk/internal/misc"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/classes/jdk/internal/misc"> windows</a>]/misc - Core Libs, HotSpot</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/module"> module</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/org/objectweb"> org/objectweb</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/org/xml"> org/xml</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/perf"> perf</a> - Runtime</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/linux/classes/jdk/internal/platform">linux</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/classes/jdk/internal/platform"> share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/classes/jdk/internal/platform"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/classes/jdk/internal/platform"> windows</a>]/platform - HotSpot</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/ref"> ref</a> - Core Libs, GC</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/reflect"> reflect</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/util/random"> util/random</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/util/regex"> util/regex</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/util/xml"> util/xml</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal/vm"> vm</a> - HotSpot</li> </ul> </li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/sun/invoke"> invoke</a> - Core Libs</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/share/classes/java/io">share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/classes/sun/io"> sun</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/classes/java/io"> unix</a>]/io - Core Libs</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/macosx/classes/java">macosx</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/classes/java"> share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/classes/java"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/classes/java"> windows</a>]/java <ul> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/share/classes/java/lang">share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/classes/java/lang"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/classes/java/lang"> windows</a>]/lang - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/java/math"> math</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/java/time"> time</a> - Core Libs</li> </ul> </li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/sun/launcher"> launcher</a> - Tools, Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/META-INF/services"> META-INF/services</a> - Core Libs</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/share/classes/javax/net">javax</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/macosx/classes/java/net"> macosx</a>]/net - Net</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/aix/classes/sun/nio">aix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/classes/java/nio"> java</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/linux/classes/sun/nio"> linux</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/macosx/classes/sun/nio"> macosx</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/classes/sun/nio"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/classes/sun/nio"> windows</a>]/nio - NIO</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/sun/reflect"> reflect</a> - Core Libs</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/macosx/classes/apple/security">apple</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/classes/java/security"> java</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/classes/javax/security"> javax</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/macosx/classes/apple/security"> macosx</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/classes/sun/security"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/classes/sun/security"> windows</a>]/security - Security</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/share/classes/java/text">java</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/classes/sun/text"> sun</a>]/text - I18n</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/share/classes/java/util">java</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/macosx/classes/sun/util"> macosx</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/classes/sun/util"> windows</a>]/util - I18n, Core Libs</li> </ul> </li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/aix/conf">aix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/conf">share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/conf">unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/conf"> windows</a>]/conf <ul> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/unix/conf/sdp"> sdp</a> - Net</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/conf/security"> security</a> - Security</li> </ul> </li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/share/legal">share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/legal"> windows</a>]/legal</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/share/lib/security">share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/lib/security"> windows</a>]/lib/security - Security</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/man"> man</a> <ul> <li><a href="https://github.com/openjdk/jdk/tree/master/src/src/java.base/share/man/java.1"> java.1</a> - Tools, HotSpot</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/src/java.base/share/man/keytool.1"> keytool.1</a> - Security</li> </ul> </li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/aix/native">aix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/linux/native"> linux</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/macosx/native"> macosx</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/native"> share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/native">unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/native"> windows</a>]/native <ul> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/windows/native/common"> common</a></li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/share/native/include">share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/native/include"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/native/include"> windows</a>]/include - Runtime, Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/unix/native/jspawnhelper"> jspawnhelper</a> - Tools</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/share/native/launcher">share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/native/launcher"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/native/launcher"> windows</a>]/launcher - Tools</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/aix/native/libjava">aix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/linux/native/libjava"> linux</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/macosx/native/libjava"> macosx</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/native/libjava"> share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/native/libjava"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/native/libjava"> windows</a>]/libjava - Core Libs</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/share/native/libjimage">share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/native/libjimage"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/native/libjimage"> windows</a>]/libjimage - Core Libs</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/aix/native/libjli">aix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/macosx/native/libjli"> macosx</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/native/libjli"> share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/native/libjli"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/native/libjli"> windows</a>]/libjli - Tools, Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/unix/native/libjsig"> libjsig</a> - HotSpot</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/macosx/native/libnet">macosx</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/native/libnet"> share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/native/libnet"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/native/libnet"> windows</a>]/libnet - Net</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/aix/native/libnio">aix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/linux/native/libnio"> linux</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/macosx/native/libnio"> macosx</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/native/libnio"> share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/unix/native/libnio"> unix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/native/libnio"> windows</a>]/libnio - NIO</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/macosx/native/libosxsecurity"> libosxsecurity</a> - Security</li> <li>[<a href="https://github.com/openjdk/jdk/tree/master/java.base/aix/native/libsyslookup">aix</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/share/native/libsyslookup"> share</a>, <a href="https://github.com/openjdk/jdk/tree/master/java.base/windows/native/libsyslookup"> windows</a>]/libsyslookup - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/native/libverify"> libverify</a> - Runtime</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/native/libzip"> libzip</a> - Core Libs</li> </ul> </li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/data"> share/data</a> <ul> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/data/blockedcertsconverter"> blockedcertsconverter</a> - Security</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/data/cacerts"> cacerts</a> - Security</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/data/currency"> currency</a> - I18n</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/data/lsrdata"> lsrdata</a> - I18n</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/data/publicsuffixlist"> publicsuffixlist</a> - Client Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/data/tzdata"> tzdata</a> - I18n</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.base/share/data/unicodedata"> unicodedata</a> - I18n</li> </ul> </li> </ul> </li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.compiler">java.compiler</a> - Java Language (javac)</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.datatransfer">java.datatransfer</a> - Client Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.desktop">java.desktop</a> - Client Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.instrument">java.instrument</a> - Serviceability</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.logging">java.logging</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.management">java.management</a> - Serviceability</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.management.rmi"> java.management.rmi</a> - Serviceability</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.naming">java.naming</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.net.http">java.net.http</a> - Net</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.prefs">java.prefs</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.rmi">java.rmi</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.scripting">java.scripting</a> - Tools</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.se">java.se</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.security.jgss"> java.security.jgss</a> - Security</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.security.sasl"> java.security.sasl</a> - Security</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.smartcardio">java.smartcardio</a> - Security</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.sql">java.sql</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.sql.rowset">java.sql.rowset</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.transaction.xa"> java.transaction.xa</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.xml">java.xml</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/java.xml.crypto">java.xml.crypto</a> - Security</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.accessibility">jdk.accessibility</a> - Client Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.attach">jdk.attach</a> - Serviceability</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.charsets">jdk.charsets</a> - I18n, Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.compiler">jdk.compiler</a> - Java Language (javac)</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.crypto.cryptoki"> jdk.crypto.cryptoki</a> - Security</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.crypto.ec">jdk.crypto.ec</a> - Security</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.crypto.mscapi">jdk.crypto.mscapi</a> - Security</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.dynalink">jdk.dynalink</a> - Tools</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.editpad">jdk.editpad</a> - JShell</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.graal.compiler"> jdk.graal.compiler</a> - Compiler</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.graal.compiler.management"> jdk.graal.compiler.management</a> - Compiler</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.hotspot.agent">jdk.hotspot.agent</a> - Serviceability</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.httpserver">jdk.httpserver</a> - Net</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.incubator.vector"> jdk.incubator.vector</a> - Compiler</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.internal.ed">jdk.internal.ed</a> - JShell</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.internal.jvmstat"> jdk.internal.jvmstat</a> - Serviceability</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.internal.le">jdk.internal.le</a> - JShell</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.internal.opt">jdk.internal.opt</a> - Tools</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.internal.vm.ci"> jdk.internal.vm.ci</a> - Compiler</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.jartool">jdk.jartool</a> - Tools</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.javadoc">jdk.javadoc</a> - Javadoc</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.jcmd">jdk.jcmd</a> - Serviceability</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.jconsole">jdk.jconsole</a> - Serviceability</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.jdeps">jdk.jdeps</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.jdi">jdk.jdi</a> - Serviceability</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.jdwp.agent">jdk.jdwp.agent</a> - Serviceability</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.jfr">jdk.jfr</a> - JFR</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.jlink">jdk.jlink</a> - Tools</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.jpackage">jdk.jpackage</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.jshell">jdk.jshell</a> - JShell</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.jsobject">jdk.jsobject</a> - Tools</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.jstatd">jdk.jstatd</a> - Serviceability</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.localedata">jdk.localedata</a> - I18n</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.management">jdk.management</a> - Serviceability</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.management.agent"> jdk.management.agent</a> - Serviceability</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.management.jfr"> jdk.management.jfr</a> - Runtime</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.naming.dns">jdk.naming.dns</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.naming.rmi">jdk.naming.rmi</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.net">jdk.net</a> - Net</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.nio.mapmode">jdk.nio.mapmode</a> - NIO</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.sctp">jdk.sctp</a> - Net</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.security.auth">jdk.security.auth</a> - Security</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.security.jgss">jdk.security.jgss</a> - Security</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.unsupported">jdk.unsupported</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.unsupported.desktop"> jdk.unsupported.desktop</a> - Client Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.xml.dom">jdk.xml.dom</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/jdk.zipfs">jdk.zipfs</a> - Core Libs</li> <li><a href="https://github.com/openjdk/jdk/tree/master/make">make</a> - Build</li> <li><a href="https://github.com/openjdk/jdk/tree/master/test">test</a> <ul> <li>The test directories follow to a large part the same structure as the source code in <code>src</code>. The owners are the same for directories with the same names.</li> </ul> </li> <li><a href="https://github.com/openjdk/jdk/tree/master/src/utils">utils</a></li> </ul> <h3 id="directories-removed">Directories removed</h3> <ul> <li>hotspot <ul> <li><code>*.jdk</code> – Compiler (Removed in <a href="https://bugs.openjdk.org/browse/JDK-8187443">10</a>)</li> <li>share <ul> <li><code>aot</code> – Compiler (Removed in <a href="https://bugs.openjdk.org/browse/JDK-8263327">17</a>)</li> <li><code>shark</code> – Compiler (Removed in <a href="https://bugs.openjdk.org/browse/JDK-8171853">10</a>)</li> <li><code>trace</code> – Runtime (Removed in <a href="https://bugs.openjdk.org/browse/JDK-8199712">11</a>)</li> </ul> </li> </ul> </li> <li>java.base <ul> <li>man <ul> <li><code>jfr.1</code> – Runtime (Removed in <a href="https://bugs.openjdk.org/browse/JBS-8252113">16</a>)</li> </ul> </li> </ul> </li> <li><code>jdk.aot</code> – Compiler (Removed in <a href="https://bugs.openjdk.org/browse/JDK-8263327">17</a>)</li> <li><code>jdk.crypto.ucrypto</code> – Security (Removed in <a href="https://bugs.openjdk.org/browse/JDK-8241787">12</a>) <ul> <li>only available on Solaris</li> </ul> </li> <li><code>jdk.incubator.concurrent</code> – Core Libs (Removed in <a href="https://bugs.openjdk.org/browse/JDK-8306647">21</a>)</li> <li><code>jdk.internal.vm.compiler</code> – Compiler (Removed in <a href="https://bugs.openjdk.org/browse/JDK-8318027">22</a>)</li> <li><code>jdk.internal.vm.compiler.management</code> – Compiler (Removed in <a href="https://bugs.openjdk.org/browse/JDK-8318027">22</a>)</li> <li><code>jdk.pack</code> – Tools (Removed in <a href="https://bugs.openjdk.org/browse/JDK-8234596">14</a>)</li> <li><code>jdk.random</code> – Core Libs (Removed in <a href="https://bugs.openjdk.org/browse/JDK-8330005">23</a>)</li> <li><code>jdk.rmic</code> – Core Libs (Removed in <a href="https://bugs.openjdk.org/browse/JDK-8225319">15</a>)</li> <li><code>jdk.scripting.nashorn</code> – Tools (Removed in <a href="https://bugs.openjdk.org/browse/JDK-8236933">15</a>)</li> <li><code>jdk.scripting.nashorn.shell</code> – Tools (Removed in <a href="https://bugs.openjdk.org/browse/JDK-8236933">15</a>)</li> </ul> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <h1 id="about-this-guide">About This Guide</h1> <p>This guide is being maintained through the <a href="https://openjdk.org/census#guide">OpenJDK Developers’ Guide Project</a>. The source repository is available at <a href="https://github.com/openjdk/guide">GitHub</a>. The revision hash at the bottom of this page refers to the last published commit.</p> <p>Comments and questions may be sent to <a href="mailto:guide-dev@openjdk.org">guide-dev@openjdk.org</a>. Please let us know if there’s anything in the guide that isn’t clear.</p> <div class="box"> <p><a href="#" class="boxheader">To the top</a></p> </div> <br /> <div class="version">File change revision: ef416dd - <a href="https://github.com/openjdk/guide/commits/master/src/guide">Revision history</a></div> </div><div id="sidebar"><div id="openjdk-sidebar-logo"><a href="/"><img alt="OpenJDK logo" src="../images/openjdk-small.png" /></a></div><div class="links"><div class="link"><a href="/install/">Installing</a></div><div class="link"><a href="/guide/#contributing-to-an-openjdk-project">Contributing</a></div><div class="link"><a href="/guide/#reviewing-and-sponsoring-a-change">Sponsoring</a></div><div class="link"><a href="/guide/">Developers' Guide</a></div><div class="link"><a href="/groups/vulnerability/report">Vulnerabilities</a></div><div class="link"><a href="https://jdk.java.net">JDK GA/EA Builds</a></div></div><div class="links"><div class="links"><a href="https://mail.openjdk.org">Mailing lists</a></div><div class="link"><a href="https://wiki.openjdk.org">Wiki</a> · <a href="/irc">IRC</a></div><div class="link"><a href="https://mastodon.social/@openjdk" rel="me">Mastodon</a></div><div class="link"><a href="https://bsky.app/profile/openjdk.org">Bluesky</a></div></div><div class="links"><div class="links"><a href="/bylaws">Bylaws</a> · <a href="/census">Census</a></div><div class="link"><a href="/legal/">Legal</a></div></div><div class="links"><div class="links"><a href="/workshop"><b>Workshop</b></a></div></div><div class="links"><div class="links"><a href="/jeps/0"><b>JEP Process</b></a></div></div><div class="links"><div class="about">Source code</div><div class="link"><a href="https://github.com/openjdk/">GitHub</a></div><div class="link"><a href="https://hg.openjdk.org">Mercurial</a></div></div><div class="links"><div class="about">Tools</div><div class="link"><a href="http://git-scm.org/">Git</a></div><div class="link"><a href="/jtreg/">jtreg harness</a></div></div><div class="links"><div class="about">Groups</div><div class="link"><a href="/groups/">(overview)</a></div><div class="link"><a href="/groups/adoption">Adoption</a></div><div class="link"><a href="/groups/build">Build</a></div><div class="link"><a href="/groups/client-libs">Client Libraries</a></div><div class="link"><a href="/groups/csr">Compatibility & Specification Review</a></div><div class="link"><a href="/groups/compiler">Compiler</a></div><div class="link"><a href="/groups/conformance">Conformance</a></div><div class="link"><a href="/groups/core-libs">Core Libraries</a></div><div class="link"><a href="/groups/gb">Governing Board</a></div><div class="link"><a href="/groups/hotspot">HotSpot</a></div><div class="link"><a href="/groups/ide-support">IDE Tooling & Support</a></div><div class="link"><a href="/groups/i18n">Internationalization</a></div><div class="link"><a href="/groups/jmx">JMX</a></div><div class="link"><a href="/groups/members">Members</a></div><div class="link"><a href="/groups/net">Networking</a></div><div class="link"><a href="/groups/porters">Porters</a></div><div class="link"><a href="/groups/quality">Quality</a></div><div class="link"><a href="/groups/security">Security</a></div><div class="link"><a href="/groups/serviceability">Serviceability</a></div><div class="link"><a href="/groups/vulnerability">Vulnerability</a></div><div class="link"><a href="/groups/web">Web</a></div></div><div class="links"><div class="about">Projects</div><div class="link">(<a href="/projects/">overview</a>, <a href="/projects/archive">archive</a>)</div><div class="link"><a href="/projects/amber">Amber</a></div><div class="link"><a href="/projects/babylon">Babylon</a></div><div class="link"><a href="/projects/crac">CRaC</a></div><div class="link"><a href="/projects/code-tools">Code Tools</a></div><div class="link"><a href="/projects/coin">Coin</a></div><div class="link"><a href="/projects/cvmi">Common VM Interface</a></div><div class="link"><a href="/projects/guide">Developers' Guide</a></div><div class="link"><a href="/projects/dio">Device I/O</a></div><div class="link"><a href="/projects/duke">Duke</a></div><div class="link"><a href="/projects/galahad">Galahad</a></div><div class="link"><a href="/projects/graal">Graal</a></div><div class="link"><a href="/projects/icedtea">IcedTea</a></div><div class="link"><a href="/projects/jdk7">JDK 7</a></div><div class="link"><a href="/projects/jdk8">JDK 8</a></div><div class="link"><a href="/projects/jdk8u">JDK 8 Updates</a></div><div class="link"><a href="/projects/jdk9">JDK 9</a></div><div class="link"><a href="/projects/jdk">JDK</a> (…, <a href="/projects/jdk/23">23</a>, <a href="/projects/jdk/24">24</a>, <a href="/projects/jdk/25">25</a>)</div><div class="link"><a href="/projects/jdk-updates">JDK Updates</a></div><div class="link"><a href="/projects/jigsaw">Jigsaw</a></div><div class="link"><a href="/projects/kona">Kona</a></div><div class="link"><a href="/projects/kulla">Kulla</a></div><div class="link"><a href="/projects/lanai">Lanai</a></div><div class="link"><a href="/projects/leyden">Leyden</a></div><div class="link"><a href="/projects/lilliput">Lilliput</a></div><div class="link"><a href="/projects/locale-enhancement">Locale Enhancement</a></div><div class="link"><a href="/projects/loom">Loom</a></div><div class="link"><a href="/projects/jmm">Memory Model Update</a></div><div class="link"><a href="/projects/metropolis">Metropolis</a></div><div class="link"><a href="/projects/jmc">Mission Control</a></div><div class="link"><a href="/projects/mlvm">Multi-Language VM</a></div><div class="link"><a href="/projects/nashorn">Nashorn</a></div><div class="link"><a href="/projects/nio">New I/O</a></div><div class="link"><a href="/projects/openjfx">OpenJFX</a></div><div class="link"><a href="/projects/panama">Panama</a></div><div class="link"><a href="/projects/penrose">Penrose</a></div><div class="link"><a href="/projects/aarch32-port">Port: AArch32</a></div><div class="link"><a href="/projects/aarch64-port">Port: AArch64</a></div><div class="link"><a href="/projects/bsd-port">Port: BSD</a></div><div class="link"><a href="/projects/haiku-port">Port: Haiku</a></div><div class="link"><a href="/projects/macosx-port">Port: Mac OS X</a></div><div class="link"><a href="/projects/mips-port">Port: MIPS</a></div><div class="link"><a href="/projects/mobile">Port: Mobile</a></div><div class="link"><a href="/projects/ppc-aix-port">Port: PowerPC/AIX</a></div><div class="link"><a href="/projects/riscv-port">Port: RISC-V</a></div><div class="link"><a href="/projects/s390x-port">Port: s390x</a></div><div class="link"><a href="/projects/sctp">SCTP</a></div><div class="link"><a href="/projects/shenandoah">Shenandoah</a></div><div class="link"><a href="/projects/skara">Skara</a></div><div class="link"><a href="/projects/sumatra">Sumatra</a></div><div class="link"><a href="/projects/tsan">Tsan</a></div><div class="link"><a href="/projects/valhalla">Valhalla</a></div><div class="link"><a href="/projects/verona">Verona</a></div><div class="link"><a href="/projects/visualvm">VisualVM</a></div><div class="link"><a href="/projects/wakefield">Wakefield</a></div><div class="link"><a href="/projects/zero">Zero</a></div><div class="link"><a href="/projects/zgc">ZGC</a></div></div><div class="buttons"><a href="https://oracle.com"><img alt="Oracle logo" src="../images/oracle.png" /></a></div></div><div id="footer"> © 2025 Oracle Corporation and/or its affiliates <br /><a href="/legal/tou/">Terms of Use</a> · License: <a href="/legal/gplv2+ce.html">GPLv2</a> · <a href="https://www.oracle.com/us/legal/privacy/">Privacy</a> · <a href="https://openjdk.org/legal/openjdk-trademark-notice.html">Trademarks</a></div><script type="text/javascript" src="/NzNeGH/Vw/i6/NOu5/EwFb8mKAtw/Q3a1kkr6kYStt1/PW02AQ/Fl/cBc2srDW8B"></script></body></html>