0% found this document useful (0 votes)
10 views

java-openjdk

The Microsoft Build of OpenJDK is a free, open-source distribution of OpenJDK that includes Long-Term Support binaries for Java 11 and Java 17 across various platforms. It provides installation options through native installers, package managers, and downloadable archives, ensuring compatibility and ease of use. Developers can provide feedback and access additional resources through GitHub and the Microsoft website.

Uploaded by

Khaled Elbedri
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

java-openjdk

The Microsoft Build of OpenJDK is a free, open-source distribution of OpenJDK that includes Long-Term Support binaries for Java 11 and Java 17 across various platforms. It provides installation options through native installers, package managers, and downloadable archives, ensuring compatibility and ease of use. Developers can provide feedback and access additional resources through GitHub and the Microsoft website.

Uploaded by

Khaled Elbedri
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 91

Tell us about your PDF experience.

Microsoft Build of OpenJDK


Overview and getting-started material on the Microsoft Build of OpenJDK.

Microsoft Build of OpenJDK

b GET STARTED

Overview

Download the JDK

Install the JDK

Container images

Java runtimes with jlink

Security and Cryptography

Configure timezones

Support
About the Microsoft Build of OpenJDK
Article • 04/04/2023

The Microsoft Build of OpenJDK is a no-cost distribution of OpenJDK that's open source
and available for free for anyone to deploy anywhere. It includes Long-Term Support
(LTS) binaries for Java 11 and Java 17 on x64 server and desktop environments on
macOS, Linux, and Windows, AArch64/ARM64 on Linux and Windows, binaries for
macOS on Apple Silicon (AArch64/M1), and musl libc compiled binaries for Alpine Linux
on x64.

For download packages and installers, see Download the Microsoft Build of OpenJDK.

The Microsoft Build of OpenJDK binaries are based on OpenJDK source code, following
the same build scripts used by the Eclipse Adoptium project and tested against the
Eclipse Adoptium Quality Assurance suite (including OpenJDK project tests). Our
generally available binaries have passed the Java Technology Compatibility Kit (TCK)
which is used to verify compatibility with the Java specifications. The Microsoft Build of
OpenJDK is a drop-in replacement for any other OpenJDK distribution available in the
Java ecosystem.

If you're a Microsoft Azure customer, you can try it now. Just visit Azure Cloud Shell on
your browser or in the Windows Terminal.

Microsoft Build of OpenJDK binaries may contain backported fixes and enhancements
we deem important to our customers and our internal users. Some of these may have
not yet been formally backported upstream and are clearly signposted in our release
notes. This allows us to expedite improvements and fixes while we proceed to upstream
those changes in parallel. Updates will be free and available to every Java developer to
deploy anywhere.

Provide feedback on the Microsoft Build of


OpenJDK
Send us your comments, thoughts, and ideas to help us improve the Microsoft Build of
OpenJDK. Visit our OpenJDK discussions page on GitHub to send us your feedback.

Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Download the Microsoft Build of
OpenJDK
Article • 01/22/2025

This article provides links to download the Microsoft Build of OpenJDK.

For instructions on how to install, see the Install page. Supported installation methods
include:

ノ Expand table

Graphical installation Package manager

MSI Winget

PKG Homebrew

apt (Ubuntu)

apt (Debian)

yum (CentOS)

The following tables provide links to the package files for GA releases, and their
.sha256sum.txt and .sig files.

OpenJDK 21

OpenJDK 21.0.6 LTS | See previous releases

ノ Expand table

Platform Architecture Type Download link Other files

x64

Linux x64 tar.gz microsoft-jdk-21.0.6-linux-x64.tar.gz sha256 / sig

macOS x64 pkg microsoft-jdk-21.0.6-macos-x64.pkg sha256

macOS x64 tar.gz microsoft-jdk-21.0.6-macos-x64.tar.gz sha256 / sig

Windows x64 msi microsoft-jdk-21.0.6-windows-x64.msi sha256


Platform Architecture Type Download link Other files

Windows x64 zip microsoft-jdk-21.0.6-windows-x64.zip sha256 / sig

AArch64

Linux AArch64 / tar.gz microsoft-jdk-21.0.6-linux- sha256 / sig


ARM64 aarch64.tar.gz

macOS Apple Silicon pkg microsoft-jdk-21.0.6-macos- sha256


aarch64.pkg

macOS Apple Silicon tar.gz microsoft-jdk-21.0.6-macos- sha256 / sig


aarch64.tar.gz

Windows AArch64 / msi microsoft-jdk-21.0.6-windows- sha256


ARM64 aarch64.msi

Windows AArch64 / zip microsoft-jdk-21.0.6-windows- sha256 / sig


ARM64 aarch64.zip

OpenJDK 17

OpenJDK 17.0.14 LTS | See previous releases

ノ Expand table

Platform Architecture Type Download link Other files

x64

Alpine x64 (musl) tar.gz microsoft-jdk-17.0.14-alpine-x64.tar.gz sha256 / sig

Linux x64 tar.gz microsoft-jdk-17.0.14-linux-x64.tar.gz sha256 / sig

macOS x64 pkg microsoft-jdk-17.0.14-macos-x64.pkg sha256

macOS x64 tar.gz microsoft-jdk-17.0.14-macos-x64.tar.gz sha256 / sig

Windows x64 msi microsoft-jdk-17.0.14-windows-x64.msi sha256

Windows x64 zip microsoft-jdk-17.0.14-windows-x64.zip sha256 / sig

AArch64

Linux AArch64 / tar.gz microsoft-jdk-17.0.14-linux- sha256 / sig


ARM64 aarch64.tar.gz
Platform Architecture Type Download link Other files

macOS Apple Silicon pkg microsoft-jdk-17.0.14-macos- sha256


aarch64.pkg

macOS Apple Silicon tar.gz microsoft-jdk-17.0.14-macos- sha256 / sig


aarch64.tar.gz

Windows AArch64 / msi microsoft-jdk-17.0.14-windows- sha256


ARM64 aarch64.msi

Windows AArch64 / zip microsoft-jdk-17.0.14-windows- sha256 / sig


ARM64 aarch64.zip

OpenJDK 11

OpenJDK 11.0.26 LTS | See previous releases

ノ Expand table

Platform Architecture Type Download link Other files

x64

Alpine x64 (musl) tar.gz microsoft-jdk-11.0.26-alpine-x64.tar.gz sha256 / sig

Linux x64 tar.gz microsoft-jdk-11.0.26-linux-x64.tar.gz sha256 / sig

macOS x64 pkg microsoft-jdk-11.0.26-macos-x64.pkg sha256

macOS x64 tar.gz microsoft-jdk-11.0.26-macos-x64.tar.gz sha256 / sig

Windows x64 msi microsoft-jdk-11.0.26-windows-x64.msi sha256

Windows x64 zip microsoft-jdk-11.0.26-windows-x64.zip sha256 / sig

AArch64

Linux AArch64 / tar.gz microsoft-jdk-11.0.26-linux- sha256 / sig


ARM64 aarch64.tar.gz

macOS Apple Silicon pkg microsoft-jdk-11.0.26-macos- sha256


aarch64.pkg

macOS Apple Silicon tar.gz microsoft-jdk-11.0.26-macos- sha256 / sig


aarch64.tar.gz

Windows AArch64 / msi microsoft-jdk-11.0.26-windows- sha256


Platform Architecture Type Download link Other files

ARM64 aarch64.msi

Windows AArch64 / zip microsoft-jdk-11.0.26-windows- sha256 / sig


ARM64 aarch64.zip

OpenJDK 8
If you still require Java 8, please download any of the Eclipse Temurin builds of OpenJDK
8 from the Eclipse Adoptium project.

Linux DEB and RPM packages


Linux Packages (RPM and DEB files) are available at packages.microsoft.com .

For more information see Install the Microsoft Build of OpenJDK.

Container images
For use of Microsoft Build of OpenJDK in container images, see Container images for the
Microsoft Build of OpenJDK.

Debug symbols and source code


The following tables provide links to the debug symbols of all platforms and
architectures, and the source code.

OpenJDK 21.0.6 LTS

ノ Expand table

Platform Architecture Type Download link Other


files

x64

Linux x64 tar.gz microsoft-jdk-debugsymbols-21.0.6-linux- sha256


x64.tar.gz

macOS x64 tar.gz microsoft-jdk-debugsymbols-21.0.6-macos- sha256


x64.tar.gz
Platform Architecture Type Download link Other
files

Windows x64 zip microsoft-jdk-debugsymbols-21.0.6-windows- sha256


x64.zip

AArch64

Linux AArch64 / tar.gz microsoft-jdk-debugsymbols-21.0.6-linux- sha256


ARM64 aarch64.tar.gz

macOS Apple Silicon tar.gz microsoft-jdk-debugsymbols-21.0.6-macos- sha256


aarch64.tar.gz

Windows AArch64 / zip microsoft-jdk-debugsymbols-21.0.6-windows- sha256


ARM64 aarch64.zip

All

Source NA GitHub https://github.com/microsoft/openjdk-


Code jdk21u/tree/release/jdk-21.0.6_7

OpenJDK 17.0.14 LTS

ノ Expand table

Platform Architecture Type Download link Other


files

x64

Alpine x64 (musl) tar.gz microsoft-jdk-debugsymbols-17.0.14-alpine- sha256


x64.tar.gz

Linux x64 tar.gz microsoft-jdk-debugsymbols-17.0.14-linux- sha256


x64.tar.gz

macOS x64 tar.gz microsoft-jdk-debugsymbols-17.0.14-macos- sha256


x64.tar.gz

Windows x64 zip microsoft-jdk-debugsymbols-17.0.14- sha256


windows-x64.zip

AArch64

Linux AArch64 / tar.gz microsoft-jdk-debugsymbols-17.0.14-linux- sha256


ARM64 aarch64.tar.gz

macOS Apple Silicon tar.gz microsoft-jdk-debugsymbols-17.0.14-macos- sha256


aarch64.tar.gz
Platform Architecture Type Download link Other
files

Windows AArch64 / zip microsoft-jdk-debugsymbols-17.0.14- sha256


ARM64 windows-aarch64.zip

All

Source NA GitHub https://github.com/microsoft/openjdk-


Code jdk17u/tree/release/jdk-17.0.14_7

OpenJDK 11.0.26 LTS

ノ Expand table

Platform Architecture Type Download link Other


files

x64

Alpine x64 (musl) tar.gz microsoft-jdk-debugsymbols-11.0.26-alpine- sha256


x64.tar.gz

Linux x64 tar.gz microsoft-jdk-debugsymbols-11.0.26-linux- sha256


x64.tar.gz

macOS x64 tar.gz microsoft-jdk-debugsymbols-11.0.26-macos- sha256


x64.tar.gz

Windows x64 zip microsoft-jdk-debugsymbols-11.0.26- sha256


windows-x64.zip

AArch64

Linux AArch64 / tar.gz microsoft-jdk-debugsymbols-11.0.26-linux- sha256


ARM64 aarch64.tar.gz

macOS Apple Silicon tar.gz microsoft-jdk-debugsymbols-11.0.26-macos- sha256


aarch64.tar.gz

Windows AArch64 / zip microsoft-jdk-debugsymbols-11.0.26- sha256


ARM64 windows-aarch64.zip

All

Source NA GitHub https://github.com/microsoft/openjdk-


Code jdk11u/tree/release/jdk-11.0.26_4
Public key to verify signature files
To verify the .sig files, download and use the public key .

URLs for major versions only


Developers can also obtain the latest packages of an LTS release by using URLs without
the specific minor version. For example, the following URLs will download the latest
version of OpenJDK 21:

Linux

Bash

curl -OL https://aka.ms/download-jdk/microsoft-jdk-21-linux-x64.tar.gz

macOS

zsh

curl -OL https://aka.ms/download-jdk/microsoft-jdk-21-macOS-x64.tar.gz

Windows

PowerShell

Invoke-WebRequest -Uri https://aka.ms/download-jdk/microsoft-jdk-21-windows-


x64.zip

For a complete list of available URLs and versions, see this page.

Previous releases
This page only lists the latest updates available. To download older releases, visit this
document.

Provide feedback on the Microsoft Build of


OpenJDK
Send us your comments, thoughts, and ideas to help us improve the Microsoft Build of
OpenJDK. Visit our OpenJDK discussions page on GitHub to send us your feedback.
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Install the Microsoft Build of OpenJDK
Article • 08/29/2024

This article describes how to install the Microsoft Build of OpenJDK. To get the files
mentioned in this article, see Download the Microsoft Build of OpenJDK.

ZIP and TAR.GZ packages


For Windows, Linux, and macOS, we produce ZIP (Windows) and TAR.GZ (Linux/macOS)
packages. To install, extract one of these packages in a folder of your choice, then set
the JAVA_HOME environment variable to that folder.

Alternately, you can use native installers for your OS of choice, as described in the next
section.

Native installers
For Windows, we produce an MSI installer with a graphical interface. For macOS, we
produce a PKG installer with similar features. These installers will automatically make the
JDK tools available in your PATH .

For Linux, we produce DEB and RPM packages to be used with apt and rpm .

The following sections provide instructions for these installers.

Install on Windows
To install on any version of Windows, you can use the MSI packages or the ZIP package.
If you're on Windows 10 or later, you can use the Windows Package Manager from your
Windows Terminal.

Install on Windows via MSI


The MSI installer provides both a graphical and a console-only installation method. If
you double-click on the MSI file, it will launch the traditional Windows application
installer, where you can follow the instructions on the screen.

For widescale deployment, you can install the MSI on the command line using the
following steps:
1. Download the .msi file. For more information, see Download the Microsoft Build of
OpenJDK.

2. Choose the features you want to install from the following table:

ノ Expand table

Feature Description

FeatureMain Core installation (DEFAULT)

FeatureEnvironment Update the PATH environment variable. (DEFAULT)

FeatureJarFileRunWith Associate .jar files with Java applications. (DEFAULT)

FeatureJavaHome Update the JAVA_HOME environment variable.

FeatureOracleJavaSoft Updates registry keys HKLM\SOFTWARE\JavaSoft\ .

7 Note

You can use FeatureOracleJavaSoft to prevent Oracle Java launching from


PATH when Microsoft Build of OpenJDK is uninstalled. Reinstall Oracle Java if
you need to restore the Oracle registry keys.

You can use optional parameters that group some of the features together, as
shown in the following example:

ノ Expand table

Parameter Features

INSTALLLEVEL=1 FeatureMain,FeatureEnvironment,FeatureJarFileRunWith

3. Run the msiexec command command on the target workstation. Use the selected
features, as shown in the following example.

Windows Command Prompt

msiexec /i <package>.msi
ADDLOCAL=FeatureMain,FeatureEnvironment,FeatureJarFileRunWith,FeatureJa
vaHome INSTALLDIR="c:\Program Files\Microsoft\" /quiet

7 Note
You must use INSTALLDIR with FeatureMain .

This example silently installs the Microsoft Build of OpenJDK, updates the PATH ,
associates .jar files with Java applications, and defines JAVA_HOME .

Install on Windows with the Windows Package


Manager (winget)
To install with the Windows Package Manager, first install winget, and then open the
Windows Terminal.

Next, use the following command to search for the Microsoft Build of OpenJDK
packages:

PowerShell

winget search Microsoft.OpenJDK

You'll see output similar to the following:

Output

Name Id Version
--------------------------------------------------------------
Microsoft Build of OpenJDK 21 Microsoft.OpenJDK.21 21.0.0

You can now install the package by referencing the Id shown above, using the following
command:

PowerShell

winget install Microsoft.OpenJDK.21

This command produces an output similar to the following:

Output

Found Microsoft Build of OpenJDK 21 [Microsoft.OpenJDK.21]


This application is licensed to you by its owner.
Microsoft is not responsible for, nor does it grant any licences to, third-
party packages.
Downloading https://aka.ms/download-jdk/microsoft-jdk-21.0.0-windows-x64.msi
██████████████████████████████ 160 MB / 160 MB
Successfully verified installer hash
Starting package install...
Successfully installed

Install on macOS
Packages for macOS are available through Homebrew or as standalone downloads in
PKG or TAR.GZ formats.

To install the latest version with Homebrew:

Bash

brew install --cask microsoft-openjdk

This command produces a output similar to the following:

Output

==> Downloading https://aka.ms/download-jdk/microsoft-jdk-21.0.0-macos-


x64.pkg
Already downloaded:
/Users/foobar/Library/Caches/Homebrew/downloads/c3df619c6411aa15151d0306a6a0
f9760ff7ab0b54d0b00daade382500369c81--microsoft-jdk-21.0.0-macos-x64.pkg
==> Installing Cask microsoft-openjdk
==> Running installer for microsoft-openjdk; your password may be necessary.
Package installers may write to any location; options such as `--appdir` are
ignored.
Password:
installer: Package name is Microsoft Build of OpenJDK
installer: Installing at base path /
installer: The install was successful.
🍺 microsoft-openjdk was successfully installed!

7 Note

The package microsoft-openjdk points to the latest version of the Microsoft Build
of OpenJDK.

To install other major versions with Homebrew:

Bash

brew install --cask microsoft-openjdk@11


# OR
brew install --cask microsoft-openjdk@17
# OR
brew install --cask microsoft-openjdk@21

To install on macOS with the TAR.GZ package, just extract the file into a location. The
JDK will be inside <location>/jdk-<version>/Contents/Home .

To install using the PKG installer, open the installer and follow the instructions. By
default, the JDK will be installed at /Library/Java/JavaVirtualMachines/microsoft-
21.jdk/Contents/Home .

Uninstall on macOS
To uninstall the Microsoft Build of OpenJDK installed through Homebrew or PKG, use
the following commands:

Bash

sudo rm -rf /Library/Java/JavaVirtualMachines/microsoft-21.jdk


sudo pkgutil --forget com.microsoft.21.jdk

To uninstall the package installed through the TAR.GZ package, simply delete the folder.

Install on Ubuntu
To install on Ubuntu 18.04, 20.04, and 22.04 LTS versions, open a terminal and run the
following commands:

Bash

# Valid values are only '18.04', '20.04', and '22.04'


# For other versions of Ubuntu, please use the tar.gz package
ubuntu_release=`lsb_release -rs`
wget
https://packages.microsoft.com/config/ubuntu/${ubuntu_release}/packages-
microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb

After the repository is added, install the Microsoft Build of OpenJDK by running the
following commands:

Bash
sudo apt-get install apt-transport-https
sudo apt-get update
sudo apt-get install msopenjdk-21

7 Note

You may have to update your default JDK selection, see here for details.

Install on Debian

Debian 10 - 12

2 Warning

As of July 2024, official support for Debian 10 has ended. All published JDKs up to
July 2024 remain available, but will not recieve continued updates or support

To install on Debian 10 through 12, open a terminal and run the following commands:

Bash

sudo apt update


sudo apt install wget lsb-release -y
wget https://packages.microsoft.com/config/debian/$(lsb_release -
rs)/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb

After the repository is added, run the following commands:

Bash

sudo apt update


sudo apt install msopenjdk-21

7 Note

You may have to update your default JDK selection, see here for details.

Debian 9
2 Warning

As of July 2024, official support for Debian 9 has ended. All published JDKs up to
July 2024 remain available, but will not recieve continued updates or support

To install on Debian 9, open a terminal and run the following commands:

Bash

wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor


> packages.microsoft.gpg
sudo install -o root -g root -m 644 packages.microsoft.gpg
/etc/apt/trusted.gpg.d/
wget -q https://packages.microsoft.com/config/debian/9/prod.list -O
/etc/apt/sources.list.d/microsoft-prod.list

After the repository is added, run the following commands:

Bash

sudo apt-get install apt-transport-https


sudo apt-get update
sudo apt-get install msopenjdk-21

7 Note

You may have to update your default JDK selection, see here for details.

Install on CentOS 7 (RPM)


To install on CentOS 7, open a terminal and run the following command:

Bash

sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-


microsoft-prod.rpm

After the repository is added, run the following command:

Bash

sudo yum install msopenjdk-21


7 Note

RPM packages for msopenjdk-21 may not update automatically to the latest minor
version. To check for the available/latest versions, run yum -v list msopenjdk-21 .
Then, run yum install msopenjdk-21-<version> to force update to the version
specified. Example: yum install msopenjdk-21-21.0.0-1

Install on Alpine (TAR.GZ)


To install on Alpine, simply download a tar.gz package for Alpine (see the download
page) and extract the folder.

7 Note

Alpine is only supported for JDK 11 and JDK 17. We will no longer be supporting
alpine for JDK21 onward.

Change the default JDK on Linux


If you have several versions of OpenJDK installed on your system, use the following
command to set the Microsoft Build of OpenJDK as the default:

For Debian/Ubuntu:

Bash

sudo update-java-alternatives --set msopenjdk-21-amd64

For CentOS, you can use the command alternative .

Provide feedback on the Microsoft Build of


OpenJDK
Send us your comments, thoughts, and ideas to help us improve the Microsoft Build of
OpenJDK. Visit our OpenJDK discussions page on GitHub to send us your feedback.

Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Container images for the Microsoft
Build of OpenJDK
Article • 08/08/2024

This article provides information on the available container images for the Microsoft
Build of OpenJDK.

Linux-based images
We currently supply Linux-based container images for Ubuntu and Microsoft CBL-
Mariner, now known as Azure Linux . The images are published in the Microsoft
Artifact Registry located at mcr.microsoft.com/openjdk/jdk .

To pull the latest image for a specific tag, use the following command:

Bash

docker pull mcr.microsoft.com/openjdk/jdk:<tag>

The following table shows the tag to use for your Linux distribution and JDK version.

ノ Expand table

Base OS OpenJDK 21 OpenJDK 17 OpenJDK 11 OpenJDK 8

Ubuntu 22.04 21-ubuntu 17-ubuntu 11-ubuntu N/A

CBL Mariner 2.0 21-mariner 17-mariner 11-mariner 8-mariner

CBL-Mariner 2.0 Distroless 21-distroless 17-distroless 11-distroless 8-distroless

Note: Images for OpenJDK 8 ship with binaries of Eclipse Temurin, from the Eclipse
Adoptium project.

Architectures
The images above are offered for both amd64 and arm64 architectures. Your container
runtime shall pull the right image based on your environment. To force a pull of an
image for a specific architecture, use the following:

Bash
$ docker pull --platform=linux/arm64 mcr.microsoft.com/openjdk/jdk:21-
mariner

To force an architecture inside a Dockerfile , you may use the following:

Dockerfile

FROM --platform=linux/arm64 mcr.microsoft.com/openjdk/jdk:21-mariner AS


build
# ...

For more information on building multi-platform container images, check the


documentation of your container runtime. For example, Docker and Podman .

How to use these images


Create a Dockerfile with the following contents:

Dockerfile

# Example using MS Build of OpenJDK image directly


FROM mcr.microsoft.com/openjdk/jdk:21-ubuntu

# Continue with your application deployment


RUN mkdir /opt/app
COPY japp.jar /opt/app
CMD ["java", "-jar", "/opt/app/japp.jar"]

Distroless
The distroless images are based on the CBL-Mariner 2.0 distribution by Microsoft. They
require a different approach to deploying an application. Because the distroless images
do not contain a complete Linux distribution, there is no shell, for example.

The ENTRYPOINT of these images is already configured pointing to the java command.
Consuming Dockerfiles must use the CMD instruction to complete the command-line
arguments of the JVM launcher process.

Create a Dockerfile with the following contents:

Dockerfile

FROM mcr.microsoft.com/openjdk/jdk:21-distroless
COPY app.jar /app.jar

CMD ["-Xmx256m", "-jar", "/app.jar"]

Use a different Base OS image or version


If you prefer to use a different OS base image distribution, you can copy the JDK from
an existing pre-built image using the COPY --from instruction in a Dockerfile, similar to
the following example:

Dockerfile

# Example using MS Build of OpenJDK image with a different base image


FROM debian:buster-slim
ENV LANG en_US.UTF-8
ENV JAVA_HOME /usr/lib/jvm/msopenjdk-21-amd64
ENV PATH "${JAVA_HOME}/bin:${PATH}"
COPY --from=mcr.microsoft.com/openjdk/jdk:21-ubuntu $JAVA_HOME $JAVA_HOME

# Continue with your application deployment


RUN mkdir /opt/app
COPY japp.jar /opt/app
CMD ["java", "-jar", "/opt/app/japp.jar"]

You can also install the JDK using either yum or apt-get , or simply extracting a tar.gz
file and configuring JAVA_HOME accordingly. Read more.

Use a different version of Ubuntu


To deploy Microsoft Build of OpenJDK on different versions of Ubuntu base images,
Microsoft recommends that users author their own Dockerfiles . For reference, the
below Dockerfile builds an image with Ubuntu 24.04.

Dockerfile

# Example using MS Build of OpenJDK image with a different version of Ubuntu


FROM ubuntu:24.04
ENV LANG en_US.UTF-8
ENV JAVA_HOME /usr/lib/jvm/msopenjdk-21-amd64
ENV PATH "${JAVA_HOME}/bin:${PATH}"
COPY --from=mcr.microsoft.com/openjdk/jdk:21-ubuntu $JAVA_HOME $JAVA_HOME

# Continue with your application deployment


RUN mkdir /opt/app
COPY japp.jar /opt/app
CMD ["java", "-jar", "/opt/app/japp.jar"]

Alpine images
While Microsoft does not supply Alpine-based images, we do supply a limited set of
musl-compiled JDK binaries for Alpine Linux.

Users are welcome to create container images for Alpine Linux using the available
binaries.

Create a Dockerfile with the following contents:

Dockerfile

FROM alpine:latest

ENV JAVA_HOME=/usr/lib/jdk
ENV PATH=${PATH}:${JAVA_HOME}/bin

# Default to UTF-8 file.encoding


ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' LC_ALL='en_US.UTF-8'

# (Optional) Add extra packages for fontconfig and ttf-dejavu to support


server-side image generation
RUN apk add --no-cache fontconfig libretls musl-locales musl-locales-lang
ttf-dejavu tzdata zlib \
&& rm -rf /var/cache/apk/*

# Download and extract JDK 17


RUN wget -nv -O jdk.tar.gz https://aka.ms/download-jdk/microsoft-jdk-17-
alpine-x64.tar.gz && \
mkdir $JAVA_HOME && \
tar xf jdk.tar.gz -C $JAVA_HOME --strip-components 1 --no-same-owner

# Copy the application


COPY app.jar /app.jar

CMD [ "java", "-jar", "/app.jar" ]

Create a custom Java runtime


To create a custom Java runtime image, use a multi-stage Dockerfile similar to the
following example:

Dockerfile
# Example of custom Java runtime using jlink in a multi-stage container
build
FROM mcr.microsoft.com/openjdk/jdk:21-ubuntu as runtime-build

# Create a custom Java runtime


RUN $JAVA_HOME/bin/jlink \
--add-modules java.base \
--strip-debug \
--no-man-pages \
--no-header-files \
--compress=2 \
--output /javaruntime

# Define your base image. You may use any base OS and version of your
choice.
FROM debian:buster-slim
ENV LANG en_US.UTF-8
ENV JAVA_HOME /usr/lib/jvm/msopenjdk-21-amd64
ENV PATH "${JAVA_HOME}/bin:${PATH}"
COPY --from=runtime-build /javaruntime $JAVA_HOME

# Continue with your application deployment


RUN mkdir /opt/app
COPY japp.jar /opt/app
CMD ["java", "-jar", "/opt/app/japp.jar"]

For more information on creating custom Java runtimes, see Java Runtimes with jlink

Non-root user
The images come with an app user that can be optionally enabled and used by
consuming layers:

Dockerfile

FROM mcr.microsoft.com/openjdk/jdk:21-mariner

WORKDIR /home/app
COPY japp.jar japp.jar
USER app

CMD ["java", "-jar", "/opt/app/japp.jar"]

In the above example, the application binary is copied as root , since the images remain
with root by default. The application then is executed as app . The folder /home/app is
also owned by user app , giving the application a writeable filesystem.
Default locale
The images for Microsoft Build of OpenJDK are configured by default with the
en_US.UTF-8 locale. If you want to use a different locale, or a different base image as

described previously, you'll need to manually configure environment variables in your


own Dockerfile, and make sure the locale you want is installed.

For example, to use the pt_BR.UTF-8 locale on an Ubuntu-based image, you can add the
following lines to your Dockerfile:

Dockerfile

...
USER root
RUN apt-get update
RUN apt-get install -y locales

RUN sed -i '/pt_BR.UTF-8/s/^# //g' /etc/locale.gen


RUN locale-gen

ENV LANG pt_BR.UTF-8


ENV LANGUAGE pt_BR:pt
ENV LC_ALL pt_BR.UTF-8
...

This Dockerfile is provided as an example. It is not meant to suggest the most optimal
configurations.

Stay on older minor versions


Microsoft Build of OpenJDK container images are only available under the tags listed
previously. We don't supply tags for minor versions, and the major version tags always
have the latest minor version to ensure that developers will have the latest update for
any given major version.

These base images use the underlying package manager mechanism of the Linux
distributions to install the JDK package. Therefore, to stay on a particular older version,
you will need to use tools such as apt-get or yum to install the specific minor version of
the JDK.

To rollback to specific versions on different base OS images outside the list of supplied
images, for example debian:buster-slim , you can use the same approach below either
in the first stage of a muli-stage container image build, or as part of a traditional Linux
package installation flow. For more information, see the Install on Ubuntu 18.04+
section of Install the Microsoft Build of OpenJDK.

For CBL-Mariner and other OS images based on RPM/yum, see the details provided later
in this article.

For Ubuntu , and other Debian-based images, you can display all available minor versions
published in the Microsoft Linux repositories, as shown in the following Bash example
showing commands and output. The commands shown here assume the Microsoft Linux
repository is configured, as described at Install on Ubuntu 18.04+.

Bash

$ docker run --pull=always -ti --rm mcr.microsoft.com/openjdk/jdk:11-ubuntu


root@c60eacd7dd7d:/# apt-get update
...

root@c60eacd7dd7d:/# apt-cache madison msopenjdk-11


msopenjdk-11 | 11.0.23-1 | https://packages.microsoft.com/ubuntu/22.04/prod
jammy/main amd64 Packages
msopenjdk-11 | 11.0.22-1 | https://packages.microsoft.com/ubuntu/22.04/prod
jammy/main amd64 Packages
msopenjdk-11 | 11.0.21-1 | https://packages.microsoft.com/ubuntu/22.04/prod
jammy/main amd64 Packages
msopenjdk-11 | 11.0.20.1-1 |
https://packages.microsoft.com/ubuntu/22.04/prod jammy/main amd64 Packages
msopenjdk-11 | 11.0.20-3 | https://packages.microsoft.com/ubuntu/22.04/prod
jammy/main amd64 Packages
msopenjdk-11 | 11.0.20-2 | https://packages.microsoft.com/ubuntu/22.04/prod
jammy/main amd64 Packages
msopenjdk-11 | 11.0.20-1 | https://packages.microsoft.com/ubuntu/22.04/prod
jammy/main amd64 Packages
msopenjdk-11 | 11.0.19-1 | https://packages.microsoft.com/ubuntu/22.04/prod
jammy/main amd64 Packages
msopenjdk-11 | 11.0.18-1 | https://packages.microsoft.com/ubuntu/22.04/prod
jammy/main amd64 Packages
...

This Bash example shows how to have your image revert msopenjdk-11 to an older
version, say 11.0.16-1 :

Bash

root@dd24eca5bdb3:/# java -version


openjdk version "11.0.23" 2024-04-16 LTS
OpenJDK Runtime Environment Microsoft-9394293 (build 11.0.23+9-LTS)
OpenJDK 64-Bit Server VM Microsoft-9394293 (build 11.0.23+9-LTS, mixed mode,
sharing)

root@a93cd1ed8783:/# apt-get -y install -y --allow-downgrades msopenjdk-


11=11.0.16-1
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
fonts-dejavu
The following NEW packages will be installed:
fonts-dejavu
The following packages will be DOWNGRADED:
msopenjdk-11
0 upgraded, 1 newly installed, 1 downgraded, 0 to remove and 0 not upgraded.
Need to get 194 MB of archives.
After this operation, 13.0 MB disk space will be freed.
Get:1 http://archive.ubuntu.com/ubuntu jammy/universe amd64 fonts-dejavu all
2.37-2build1 [3,192 B]
Get:2 https://packages.microsoft.com/ubuntu/22.04/prod jammy/main amd64
msopenjdk-11 amd64 11.0.16-1 [194 MB]
Fetched 194 MB in 18s (10.7 MB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package fonts-dejavu.
(Reading database ... 9151 files and directories currently installed.)
Preparing to unpack .../fonts-dejavu_2.37-2build1_all.deb ...
Unpacking fonts-dejavu (2.37-2build1) ...
dpkg: warning: downgrading msopenjdk-11 from 11.0.23-1 to 11.0.16-1
Preparing to unpack .../msopenjdk-11_11.0.16-1_amd64.deb ...
update-alternatives: using /usr/lib/jvm/msopenjdk-11-amd64/lib/jfr to
provide /usr/bin/jfr (jfr) in auto mode
Unpacking msopenjdk-11 (11.0.16-1) over (11.0.23-1) ...
Setting up fonts-dejavu (2.37-2build1) ...
Setting up msopenjdk-11 (11.0.16-1) ...

To do the same thing in your Dockerfile, use the following commands:

Dockerfile

FROM mcr.microsoft.com/openjdk/jdk:11-ubuntu
...
RUN apt-get update && \
apt-get install -y --allow-downgrades msopenjdk-11=11.0.16-1
...

This Bash example uses CBL-Mariner based images:

Bash

root [ / ]# java -version


openjdk version "11.0.15" 2022-04-19 LTS
OpenJDK Runtime Environment Microsoft-32930 (build 11.0.15+10-LTS)
OpenJDK 64-Bit Server VM Microsoft-32930 (build 11.0.15+10-LTS, mixed mode)

root [ / ]# yum update


...
root [ / ]# yum list msopenjdk-11
Loaded plugin: tdnfrepogpgcheck
msopenjdk-11.x86_64 11.0.14+9_LTS-1 @System
msopenjdk-11.x86_64 11.0.10+9-1 packages-microsoft-com-prod
msopenjdk-11.x86_64 11.0.11+9-1 packages-microsoft-com-prod
msopenjdk-11.x86_64 11.0.12+7-1 packages-microsoft-com-prod
msopenjdk-11.x86_64 11.0.13+8_LTS-1 packages-microsoft-com-prod
msopenjdk-11.x86_64 11.0.14+9_LTS-1 packages-microsoft-com-prod

root [ / ]# yum install -y --nogpgcheck msopenjdk-11-11.0.15-1


Loaded plugin: tdnfrepogpgcheck

Downgrading:
msopenjdk-11 x86_64 11.0.15-1 mariner-official-microsoft 308.10M
183.75M

Total installed size: 308.10M


Total download size: 183.75M
msopenjdk-11 192678446 100%
Testing transaction
Running transaction
Installing/Updating: msopenjdk-11-11.0.15-1.x86_64
Removing: msopenjdk-11-11.0.23-1.x86_64

To do the same thing in your Dockerfile, use the following commands:

Dockerfile

FROM mcr.microsoft.com/openjdk/jdk:11-mariner
...
RUN yum update && \
yum install -y --nogpgcheck msopenjdk-11-11.0.15-1
...

Container image rebuild schedule


To ensure the highest level of security and stability, our container images are rebuilt
every Monday, Wednesday, and Friday. This regular rebuild schedule enables us to
promptly incorporate the latest security patches and updates.

You can expect the following benefits from this rebuild schedule:

Timely security updates: By rebuilding the images three times a week, we ensure
that any new security vulnerabilities are addressed quickly.
Improved stability: Regular updates help maintain the stability and performance of
your applications by including the latest bug fixes and improvements.
If you have any questions or encounter issues related to these updates, refer to this
schedule before you open a support ticket.

For more information on our support policies, see Support roadmap for the Microsoft
Build of OpenJDK.

Windows-based images
We currently do not supply Windows-based container images.

Provide feedback on the Microsoft Build of


OpenJDK
Send us your comments, thoughts, and ideas to help us improve the Microsoft Build of
OpenJDK. Visit our OpenJDK discussions page on GitHub to send us your feedback.

Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
URLs for latest updates of LTS builds
Article • 09/30/2023

These URLs are helpful for users who want to download the latest LTS builds of OpenJDK
from inside shell scripts and other automation methods, for specific major versions of
these builds.

Linux

Bash

curl -OL https://aka.ms/download-jdk/microsoft-jdk-21-linux-x64.tar.gz

macOS

zsh

curl -OL https://aka.ms/download-jdk/microsoft-jdk-21-macOS-x64.tar.gz

Windows

PowerShell

Invoke-WebRequest -Uri https://aka.ms/download-jdk/microsoft-jdk-21-windows-


x64.zip

For now we are publishing only the compressed archives and checksums for x64. If you
have use cases for PKG/DEB/RPM/MSI installers, please let us know .

OpenJDK 21 LTS
ノ Expand table

Platform Architecture Type Link

x64

Linux x64 tar.gz https://aka.ms/download-jdk/microsoft-jdk-21-linux-


x64.tar.gz

macOS x64 tar.gz https://aka.ms/download-jdk/microsoft-jdk-21-macOS-


x64.tar.gz
Platform Architecture Type Link

Windows x64 zip https://aka.ms/download-jdk/microsoft-jdk-21-windows-


x64.zip

Windows x64 msi https://aka.ms/download-jdk/microsoft-jdk-21-windows-


x64.msi

AArch64

Linux AArch64 / tar.gz https://aka.ms/download-jdk/microsoft-jdk-21-linux-


ARM64 aarch64.tar.gz

macOS Apple Silicon tar.gz https://aka.ms/download-jdk/microsoft-jdk-21-macOS-


aarch64.tar.gz

Windows AArch64 / zip https://aka.ms/download-jdk/microsoft-jdk-21-windows-


ARM64 aarch64.zip

Windows AArch64 / msi https://aka.ms/download-jdk/microsoft-jdk-21-windows-


ARM64 aarch64.msi

OpenJDK 17 LTS
ノ Expand table

Platform Architecture Type Link

x64

Alpine x64 (musl) tar.gz https://aka.ms/download-jdk/microsoft-jdk-17-alpine-


x64.tar.gz

Linux x64 tar.gz https://aka.ms/download-jdk/microsoft-jdk-17-linux-


x64.tar.gz

macOS x64 tar.gz https://aka.ms/download-jdk/microsoft-jdk-17-macOS-


x64.tar.gz

Windows x64 zip https://aka.ms/download-jdk/microsoft-jdk-17-windows-


x64.zip

Windows x64 msi https://aka.ms/download-jdk/microsoft-jdk-17-windows-


x64.msi

AArch64

Linux AArch64 / tar.gz https://aka.ms/download-jdk/microsoft-jdk-17-linux-


ARM64 aarch64.tar.gz
Platform Architecture Type Link

macOS Apple Silicon tar.gz https://aka.ms/download-jdk/microsoft-jdk-17-macOS-


aarch64.tar.gz

Windows AArch64 / zip https://aka.ms/download-jdk/microsoft-jdk-17-windows-


ARM64 aarch64.zip

Windows AArch64 / msi https://aka.ms/download-jdk/microsoft-jdk-17-windows-


ARM64 aarch64.msi

OpenJDK 11 LTS
ノ Expand table

Platform Architecture Type Link

x64

Alpine x64 (musl) tar.gz https://aka.ms/download-jdk/microsoft-jdk-11-alpine-


x64.tar.gz

Linux x64 tar.gz https://aka.ms/download-jdk/microsoft-jdk-11-linux-


x64.tar.gz

macOS x64 tar.gz https://aka.ms/download-jdk/microsoft-jdk-11-macOS-


x64.tar.gz

Windows x64 zip https://aka.ms/download-jdk/microsoft-jdk-11-windows-


x64.zip

Windows x64 msi https://aka.ms/download-jdk/microsoft-jdk-11-windows-


x64.msi

AArch64

Linux AArch64 / tar.gz https://aka.ms/download-jdk/microsoft-jdk-11-linux-


ARM64 aarch64.tar.gz

macOS Apple Silicon tar.gz https://aka.ms/download-jdk/microsoft-jdk-11-macOS-


aarch64.tar.gz

Windows AArch64 / zip https://aka.ms/download-jdk/microsoft-jdk-11-windows-


ARM64 aarch64.zip

Windows AArch64 / msi https://aka.ms/download-jdk/microsoft-jdk-11-windows-


ARM64 aarch64.msi
Checksums
To download the respective checksum sha256 file for any of the packages above,
append .sha256sum.txt to the URL.
Java Runtimes with jlink
Article • 04/04/2023

Microsoft acknowledges and supports the adoption of custom Java runtimes crafted for
specific application needs rather the use of general purpose Java runtimes. This method
of Java deployment ensures the Java runtime only contains the parts of the Java
platform that are truly needed by applications, therefore increasing security, reducing
deployment size, and enhancing performance, for both Cloud and server based Java
applications as well as desktop/GUI applications.

Traditionally, Oracle/Sun Microsystems would produce Java Runtime Environment (JRE)


installers which would contain solely the Java Virtual Machine, the Java APIs, and OS and
browser specific integrations, aimed at enabling computers for running Java applications
downloaded from the Internet, or for running Applets and Java Web Start applications
through the browser.

With the advent of modern web applications and browsers, both Applets and Java Web
Start technologies became deprecated, and browsers no longer support Java plugins.
The need for a general purpose Java Runtime Environments pre-installed on computers
became less significant overtime. With Java 9, the Applet API became deprecated (see
JEP 289 ) and with Java 17, the API became marked for removal, meaning it will
certainly be removed on a future release of Java.

Another significant change is the modularization of Java , also started with the Java 9
release (see JSR 376 ). As part of this change, developers can now use a newly added
command line in the JDK called jlink to produce a custom Java runtime specifically
designed to fit the needs of applications, to be deployed as a built-in embedded
runtime along with the application code often times as part of a container image for
Cloud-based workloads, or as part of installers for GUI-based applications.

Today, Minecraft: Java Edition is deployed to millions of Minecraft gamers with a custom
Java runtime embedded within the game. Behind online services such as LinkedIn,
Yammer, Bing, and Azure, Microsoft also deploys hundreds of thousands of JVMs using
this technique.

Create a custom Java runtime


To create a Java runtime, you must have JDK 9 or later installed on your environment.
Download and install the Microsoft Build of OpenJDK first.
Identify required modules with jdeps
The Java Platform is now segmented into modules. See the documentation of Java 17
for a full list; other versions of Java may include new modules.

The JDK tool jdeps can be used to analyze a .class file, a directory, or a JAR file, to
identify Java module dependencies, JDK internals dependencies, and other useful
information that will help developers produce Java runtimes.

shell

$ cat HelloWorld.java
public class HelloWorld {
public static void main(String args[]) {
System.out.println("Hello World!");
}
}

$ jdeps HelloWorld.class
HelloWorld.class -> java.base
<unnamed> -> java.io
java.base
<unnamed> -> java.lang
java.base

The tool jdeps indicates that this class only depends on types in the java.lang and
java.io packages, therefore it only needs the module java.base . A similar output

would be produced for a JAR file as input. With a list of the required modules, you can
now create a Java runtime.

Creating a Java runtime with jlink


To create a Java runtime from the JDK, you must know which modules you want. Use
jdeps to identify them. For details on the jlink command line tool, please see the

documentation .

Example:

shell

$ jlink \
--add-modules java.base \
--strip-debug \
--no-man-pages \
--no-header-files \
--compress=2 \
--output /javaruntime

You can now use the Java runtime located at /javaruntime to execute the application
code dependent on java.base module. The structure of the javaruntime folder
produced by jlink is similar to the JDK directory structure, and the java command line
tool to start the JVM, is located in the ./bin/ folder as usual. Given a custom Java
runtime contains all the required modules of an existing application, it can be
referenced by JAVA_HOME .

shell

$ /javaruntime/bin/java HelloWorld
Hello, World!

In the example above, the produced Java runtime on Windows consumes about 24 MB
on Windows.

Create a Java runtime with Docker container image


You can use Docker multi-stage builds to create, consume, and pack the custom Java
runtime as part of your image build. See how to create Java runtimes using Docker.

Knowledge base
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Visit Java Security and Cryptography for an explanation on how to fix this issue.

Resources
OpenJDK 11: Using jlink to customize java runtime environment (Red Hat)

Provide feedback on the Microsoft Build of


OpenJDK
Send us your comments, thoughts, and ideas to help us improve the Microsoft Build of
OpenJDK. Visit our OpenJDK discussions page on GitHub to send us your feedback.

Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Reasons to move to Java 11 and beyond
Article • 04/04/2023

The question is not if you should move to Java 11 or a later version, but when. Within
the next few years, Java 8 will no longer be supported, and users will have to move to
Java 11 or later. We argue that there are benefits to moving to Java 11 and encourage
teams to do so as soon as possible.

Since Java 8, new features have been added and enhancements have been made. There
are noticeable additions and modifications to API, and there are enhancements that
improve startup, performance, and memory usage.

Transitioning to Java 11
Transitioning to Java 11 can be done in a stepwise fashion. It is not required for code to
use Java modules to run on Java 11. Java 11 can be used to run code developed and
built with JDK 8. But there are some potential issues, primarily concerning deprecated
API, class loaders, and reflection.

The Microsoft Java Engineering Group has a guide to transition from Java 8 to Java 11.
The Java Platform, Standard Edition Oracle JDK 9 Migration Guide and The State of
the Module System: Compatibility and Migration are other useful guides.

High-level changes between Java 8 and 11


This section does not enumerate all the changes made in Java versions 9 [1], 10 [2], and
11 [3]. Changes that have an impact on performance, diagnostics, and productivity are
highlighted.

Modules [4]
Modules address issues of configuration and encapsulation that are difficult to manage
in large-scale applications running on the classpath. A module is a self-describing
collection of Java classes and interfaces, and related resources.

Modules make it possible to customize runtime configurations that contain only the
components required by an application. This customization creates a smaller footprint
and allows an application to be statically linked, using jlink , into a custom runtime for
deployment. This smaller footprint can be particularly useful in a microservices
architecture.
Internally, the JVM is able to take advantage of modules in a way that makes class-
loading more efficient. The result is a runtime that is smaller, lighter, and faster to start.
Optimization techniques used by the JVM to improve application performance can be
more effective because modules encode which components a class requires.

For programmers, modules help enforce strong encapsulation by requiring explicit


declaration of which packages a module exports and which components it requires, and
by restricting reflective access. This level of encapsulation makes an application more
secure and easier to maintain.

An application can continue to use the classpath and does not have to transition to
modules as a requisite for running on Java 11.

Profiling and diagnostics

Java Flight Recorder [5]


Java Flight Recorder (JFR) gathers diagnostic and profiling data from a running Java
application. JFR has little impact on a running Java application. The collected data can
then be analyzed with Java Mission Control (JMC) and other tools. Whereas JFR and JMC
were commercial features in Java 8, both are open source in Java 11.

Java Mission Control [6]


Java Mission Control (JMC) provides a graphical display of data collected by the Java
Flight Recorder (JFR) and is open source in Java 11. In addition to general information
about the running application, JMC allows the user to drill down into the data. JFR and
JMC can be used to diagnose runtime issues such as memory leaks, GC overhead, hot
methods, thread bottlenecks, and blocking I/O.

Unified logging [7]

Java 11 has a common logging system for all components of the JVM. This unified
logging system allows the user to define what components to log, and to what level.
This fine-grained logging is useful for performing root-cause analysis on JVM crashes
and for diagnosing performance issues in a production environment.

Low-overhead heap profiling [8]


New API has been added to the Java Virtual Machine Tool Interface (JVMTI) for sampling
Java heap allocations. The sampling has low-overhead and can be enabled continuously.
While heap allocation can be monitored with Java Flight Recorder (JFR), the sampling
method in JFR only works on allocations. The JFR implementation may also miss
allocations. In contrast, heap sampling in Java 11 can provide information about both
live and dead objects.

Application Performance Monitoring (APM) vendors are starting to utilize this new
feature and the Java Engineering Group is investigating its potential use with Azure
performance monitoring tools.

StackWalker [9]

Getting a snapshot of the stack for the current thread is often used when logging. The
problem is how much of the stack trace to log, and whether to log the stack trace at all.
For example, one may want to see the stack trace only for a certain exception from a
method. The StackWalker class (added in Java 9) gives a snapshot of the stack and
provides methods that give the programmer fine-grained control over how to consume
the stack trace.

Garbage collection [10]


The following garbage collectors are available in Java 11: Serial, Parallel, Garbage-First,
and Epsilon. The default garbage collector in Java 11 is the Garbage First Garbage
Collector (G1GC).

Three other collectors are mentioned here for completeness. The Z Garbage Collector
(ZGC) is a concurrent, low-latency collector that attempts to keep pause times under
10ms. ZGC is available as an experimental feature in Java 11. The Shenandoah collector
is a low-pause collector that reduces GC pause times by performing more garbage
collection concurrently with the running Java program. Shenandoah is an experimental
feature in Java 12, but there are backports to Java 11. The Concurrent Mark and Sweep
collector (CMS) is available but has been deprecated since Java 9.

The JVM sets GC defaults for the average use-case. Often, these defaults, and other GC
settings, need to be tuned for optimum throughput or latency, according to the
application's requirements. Properly tuning the GC requires deep knowledge of the GC,
expertise that the Microsoft Java Engineering Group provides.

G1GC

The default garbage collector in Java 11 is the G1 garbage collector (G1GC). The aim of
G1GC is to strike a balance between latency and throughput. The G1 garbage collector
attempts to achieve high throughput by meeting pause time goals with high probability.
G1GC is designed to avoid full collections, but when the concurrent collections can't
reclaim memory fast enough a fallback full GC will occur. The full GC uses the same
number of parallel worker threads as the young and mixed collections.

Parallel GC

The parallel collector is the default collector in Java 8. Parallel GC is a throughput


collector that uses multiple threads to speed up garbage collection.

Epsilon [11]
The Epsilon garbage collector handles allocations but does not reclaim any memory.
When the heap is exhausted, the JVM will shut down. Epsilon is useful for short-lived
services and for applications that are known to be garbage-free.

Improvements for docker containers [12]

Prior to Java 10, memory and CPU constraints set on a container were not recognized by
the JVM. In Java 8, for example, the JVM will default the maximum heap size to ¼ of the
physical memory of the underlying host. Starting with Java 10, the JVM uses constraints
set by container control groups (cgroups) to set memory and CPU limits (see note
below). For example, the default maximum heap size is ¼ of the container's memory
limit (e.g., 500MB for -m2G).

JVM Options were also added to give Docker container users fine-grained control over
the amount of system memory that will be used for the Java heap.

This support is enabled by default and is only available on Linux-based platforms.

7 Note

Most of the cgroup enablement work was backported to Java 8 as of jdk8u191.


Further improvements may not necessarily be backported to 8.

Multi-release jar files [13]


It is possible in Java 11 to create a jar file that contains multiple, Java-release-specific
versions of class files. Multi-release jar files make it possible for library developers to
support multiple versions of Java without having to ship multiple versions of jar files. For
the consumer of these libraries, multi-release jar files solves the issue of having to match
specific jar files to specific runtime targets.

Miscellaneous performance improvements


The following changes to the JVM have a direct impact on performance.

JEP 197: Segmented Code Cache [14] - Divides the code cache into distinct
segments. This segmentation provides better control of the JVM memory footprint,
shortens scanning time of compiled methods, significantly decreases the
fragmentation of code cache, and improves performance.

JEP 254: Compact Strings [15] - Changes the internal representation of a String
from a two bytes per char to one or two bytes per char, depending on the char
encoding. Since most Strings contain ISO-8859-1/Latin-1 characters, this change
effectively halves the amount of space required to store a String.

JEP 310: Application Class-Data Sharing [16] - Class-Data Sharing decreases


startup time by allowing archived classes to be memory-mapped at runtime.
Application Class-Data Sharing extends class-data sharing by allowing application
classes to be placed in the CDS archive. When multiple JVMs share the same
archive file, memory is saved, and the overall system response time improves.

JEP 312: Thread-Local Handshakes [17] - Makes it possible to execute a callback


on threads without performing a global VM safepoint, which helps the VM achieve
lower latency by reducing the number of global safepoints.

Lazy Allocation of Compiler Threads [18] - In tiered compilation mode, the VM


starts a large number of compiler threads. This mode is the default on systems
with many CPUs. These threads are created regardless of the available memory or
the number of compilation requests. Threads consume memory even when they
are idle (which is almost all the time), which leads to an inefficient use of resources.
To address this issue, the implementation has been changed to start only one
compiler thread of each type during startup. Starting additional threads, and
shutting down unused threads, is handled dynamically.

The following changes to the core libraries have an impact on performance of new or
modified code.

JEP 193: Variable Handles [19] - Defines a standard means to invoke the
equivalents of various java.util.concurrent.atomic and sun.misc.Unsafe operations
upon object fields and array elements, a standard set of fence operations for fine-
grained control of memory ordering, and a standard reachability-fence operation
to ensure that a referenced object remains strongly reachable.

JEP 269: Convenience Factory Methods for Collections [20] - Defines library APIs
to make it convenient to create instances of collections and maps with small
numbers of elements. The static factory methods on the collection interfaces that
create compact, unmodifiable collection instances. These instances are inherently
more efficient. The APIs create collections that are compactly represented and do
not have a wrapper class.

JEP 285: Spin-Wait Hints [21] - Provides API that allows Java to hint to the run-
time system that it is in a spin loop. Certain hardware platforms benefit from
software indication that a thread is in a busy-wait state.

JEP 321: HTTP Client (Standard) [22]- Provides a new HTTP client API that
implements HTTP/2 and WebSocket and can replace the legacy
HttpURLConnection API.

References
[1] Oracle Corporation, "Java Development Kit 9 Release Notes," (Online). Available:
https://www.oracle.com/technetwork/java/javase/9u-relnotes-3704429.html .
(Accessed November 13, 2019).

[2] Oracle Corporation, "Java Development Kit 10 Release Notes," (Online). Available:
https://www.oracle.com/technetwork/java/javase/10u-relnotes-4108739.html .
(Accessed November 13, 2019).

[3] Oracle Corporation, "Java Development Kit 11 Release Notes," (Online). Available:
https://www.oracle.com/technetwork/java/javase/11u-relnotes-5093844.html .
(Accessed November 13, 2019).

[4] Oracle Corporation, "Project Jigsaw," September 22, 2017. (Online). Available:
http://openjdk.java.net/projects/jigsaw/ . (Accessed November 13, 2019).

[5] Oracle Corporation, "JEP 328: Flight Recorder," September 9, 2018. (Online).
Available: http://openjdk.java.net/jeps/328 . (Accessed November 13, 2019).

[6] Oracle Corporation, "Mission Control," April 25, 2019. (Online). Available:
https://wiki.openjdk.java.net/display/jmc/Main . (Accessed November 13, 2019).

[7] Oracle Corporation, "JEP 158: Unified JVM Logging," February 14, 2019. (Online).
Available: http://openjdk.java.net/jeps/158 . (Accessed November 13, 2019).
[8] Oracle Corporation, "JEP 331: Low-Overhead Heap Profiling," September 5, 2018.
(Online). Available: http://openjdk.java.net/jeps/331 . (Accessed November 13, 2019).

[9] Oracle Corporation, "JEP 259: Stack-Walking API," July 18, 2017. (Online). Available:
http://openjdk.java.net/jeps/259 . (Accessed November 13, 2019).

[10] Oracle Corporation, "JEP 248: Make G1 the Default Garbage Collector," September
12, 2017. (Online). Available: http://openjdk.java.net/jeps/248 . (Accessed November
13, 2019).

[11] Oracle Corporation, "JEP 318: Epsilon: A No-Op Garbage Collector," September 24,
2018. (Online). Available: http://openjdk.java.net/jeps/318 . (Accessed November 13,
2019).

[12] Oracle Corporation, "JDK-8146115: Improve docker container detection and


resource configuration usage," September 16, 2019. (Online). Available:
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8146115 . (Accessed
November 13, 2019).

[13] Oracle Corporation, "JEP 238: Multi-Release JAR Files," June 22, 2017. (Online).
Available: http://openjdk.java.net/jeps/238 . (Accessed November 13, 2019).

[14] Oracle Corporation, "JEP 197: Segmented Code Cache," April 28, 2017. (Online).
Available: http://openjdk.java.net/jeps/197 . (Accessed November 13, 2019).

[15] Oracle Corporation, "JEP 254: Compact Strings," May 18, 2019. (Online). Available:
http://openjdk.java.net/jeps/254 . (Accessed November 13, 2019).

[16] Oracle Corporation, "JEP 310: Application Class-Data Sharing," August 17, 2018.
(Online). Available: https://openjdk.java.net/jeps/310 . (Accessed November 13, 2019).

[17] Oracle Corporation, "JEP 312: Thread-Local Handshakes," August 21, 2019. (Online).
Available: https://openjdk.java.net/jeps/312 . (Accessed November 13, 2019).

[18] Oracle Corporation, "JDK-8198756: Lazy allocation of compiler threads," Oct 29,
2018. (Online). Available: https://bugs.java.com/bugdatabase/view_bug.do?
bug_id=8198756 . (Accessed November 13, 2019).

[19] Oracle Corporation, "JEP 193: Variable Handles," August 17, 2017. (Online).
Available: https://openjdk.java.net/jeps/193 . (Accessed November 13, 2019).

[20] Oracle Corporation, "JEP 269: Convenience Factory Methods for Collections," June
26, 2017. (Online). Available: https://openjdk.java.net/jeps/269 . (Accessed November
13, 2019).
[21] Oracle Corporation, "JEP 285: Spin-Wait Hints," August 20, 2017. (Online). Available:
https://openjdk.java.net/jeps/285 . (Accessed November 13, 2019).

[22] Oracle Corporation, "JEP 321: HTTP Client (Standard)," September 27, 2018. (Online).
Available: https://openjdk.java.net/jeps/321 . (Accessed November 13, 2019).
Transition from Java 8 to Java 11
Article • 04/04/2023

There's no one-size-fits-all solution to transition code from Java 8 to Java 11. For a non-
trivial application, moving from Java 8 to Java 11 can be a significant amount of work.
Potential issues include removed API, deprecated packages, use of internal API, changes
to class loaders, and changes to garbage collection.

In general, the approaches are to try to run on Java 11 without recompiling, or to


compile with JDK 11 first. If the goal is to get an application up and running as quickly
as possible, just trying to run on Java 11 is often the best approach. For a library, the
goal will be to publish an artifact that is compiled and tested with JDK 11.

Moving to Java 11 is worth the effort. New features have been added and
enhancements have been made since Java 8. These features and enhancements improve
startup, performance, memory usage, and provide better integration with containers.
And there are additions and modifications to API that improve developer productivity.

This document touches on tools to inspect code. It also covers issues that you may run
into and recommendations for resolving them. You should also consult other guides,
such as the Oracle JDK Migration Guide . How to make existing code modular is not
covered here.

The toolbox
Java 11 has two tools, jdeprscan and jdeps, that are useful for sniffing out potential
issues. These tools can be run against existing class or jar files. You can assess the
transition effort without having to recompile.

jdeprscan looks for use of deprecated or removed API. Use of deprecated API is not a
blocking issue, but is something to look into. Is there an updated jar file? Do you need
to log an issue to address the use of deprecated API? Use of removed API is a blocking
issue that has to be addressed before you try to run on Java 11.

jdeps , which is a Java class dependency analyzer. When used with the --jdk-
internals option, jdeps tells you which class depends on which internal API. You can

continue to use internal API in Java 11, but replacing the usage should be a priority. The
OpenJDK wiki page Java Dependency Analysis Tool has recommended replacements
for some commonly used JDK internal APIs.
There are jdeps and jdeprscan plugins for both Gradle and Maven. We recommend
adding these tools to your build scripts.

Tool Gradle Plugin Maven Plugin

jdeps jdeps-gradle-plugin Apache Maven JDeps Plugin

jdeprscan jdeprscan-gradle-plugin Apache Maven JDeprScan Plugin

The Java compiler itself, javac, is another tool in your toolbox. The warnings and errors
you get from jdeprscan and jdeps will come out of the compiler. The advantage of using
jdeprscan and jdeps is that you can run these tools over existing jars and class files,
including third-party libraries.

What jdeprscan and jdeps cannot do is warn about the use of reflection to access
encapsulated API. Reflective access is checked at runtime. Ultimately, you have to run
the code on Java 11 to know with certainty.

Using jdeprscan
The easiest way to use jdeprscan is to give it a jar file from an existing build. You can
also give it a directory, such as the compiler output directory, or an individual class
name. Use the --release 11 option to get the most complete list of deprecated API. If
you want to prioritize which deprecated API to go after, dial the setting back to --
release 8 . API that was deprecated in Java 8 is likely to be removed sooner than API
that has been deprecated more recently.

Console

jdeprscan --release 11 my-application.jar

The jdeprscan tool generates an error message if it has trouble resolving a dependent
class. For example, error: cannot find class org/apache/logging/log4j/Logger . Adding
dependent classes to the --class-path or using the application class-path is
recommended, but the tool will continue the scan without it. The argument is
‑‑class‑path. No other variations of the class-path argument will work.

Console

jdeprscan --release 11 --class-path log4j-api-2.13.0.jar my-application.jar


error: cannot find class sun/misc/BASE64Encoder
class com/company/Util uses deprecated method java/lang/Double::<init>(D)V
This output tells us that the com.company.Util class is calling a deprecated constructor
of the java.lang.Double class. The javadoc will recommend API to use in place of
deprecated API. No amount of work will resolve the error: cannot find class
sun/misc/BASE64Encoder because it is API that has been removed. Since Java 8,
java.util.Base64 should be used.

Run jdeprscan --release 11 --list to get a sense of what API has been deprecated
since Java 8. To get a list of API that has been removed, run jdeprscan --release 11 --
list --for-removal .

Using jdeps
Use jdeps , with the --jdk-internals option to find dependencies on JDK internal API.
The command line option --multi-release 11 is needed for this example because log4j-
core-2.13.0.jar is a multi-release jar file . Without this option, jdeps will complain if it
finds a multi-release jar file. The option specifies which version of class files to inspect.

Console

jdeps --jdk-internals --multi-release 11 --class-path log4j-core-2.13.0.jar


my-application.jar
Util.class -> JDK removed internal API
Util.class -> jdk.base
Util.class -> jdk.unsupported
com.company.Util -> sun.misc.BASE64Encoder JDK internal API
(JDK removed internal API)
com.company.Util -> sun.misc.Unsafe JDK internal API
(jdk.unsupported)
com.company.Util -> sun.nio.ch.Util JDK internal API
(java.base)

Warning: JDK internal APIs are unsupported and private to JDK implementation
that are
subject to be removed or changed incompatibly and could break your
application.
Please modify your code to eliminate dependence on any JDK internal APIs.
For the most recent update on JDK internal API replacements, please check:
https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool

JDK Internal API Suggested Replacement


---------------- ---------------------
sun.misc.BASE64Encoder Use java.util.Base64 @since 1.8
sun.misc.Unsafe See
http://openjdk.java.net/jeps/260
The output gives some good advice on eliminating use of JDK internal API! Where
possible, the replacement API is suggested. The name of the module where the package
is encapsulated is given in the parentheses. The module name can be used with --add-
exports or --add-opens if it is necessary to explicitly break encapsulation .

The use of sun.misc.BASE64Encoder or sun.misc.BASE64Decoder will result in a


java.lang.NoClassDefFoundError in Java 11. Code that uses these APIs has to be modified
to use java.util.Base64.

Try to eliminate the use of any API coming from the module jdk.unsupported. API from
this module will reference JDK Enhancement Proposal (JEP) 260 as a suggested
replacement. In a nutshell, JEP 260 says that the use of internal API will be supported
until replacement API is available. Even though your code may use JDK internal API, it
will continue to run, for a while at least. Do take a look at JEP 260 since it does point to
replacements for some internal API. variable handles can be used in place of some
sun.misc.Unsafe API, for example.

jdeps can do more than just scan for use of JDK internals. It is a useful tool for analyzing
dependencies and for generating a module-info files. Take a look at the
documentation for more.

Using javac
Compiling with JDK 11 will require updates to build scripts, tools, test frameworks, and
included libraries. Use the -Xlint:unchecked option for javac to get the details on use of
JDK internal API and other warnings. It may also be necessary to use --add-opens or --
add-reads to expose encapsulated packages to the compiler (see JEP 261 ).

Libraries can consider packaging as a multi-release jar file . Multi-release jar files allow
you to support both Java 8 and Java 11 runtimes from the same jar file. They do add
complexity to the build. How to build multi-release jars is beyond the scope of this
document.

Running on Java 11
Most applications should run on Java 11 without modification. The first thing to try is to
run on Java 11 without recompiling the code. The point of just running is to see what
warnings and errors come out of the execution. This approach gets an
application to run on Java 11 more quickly by focusing on the minimum that needs to
be done.
Most of the problems you may encounter can be resolved without having to recompile
code. If an issue has to be fixed in the code, then make the fix but continue to compile
with JDK 8. If possible, work on getting the application to run with java version 11
before compiling with JDK 11.

Check command line options


Before running on Java 11, do a quick scan of the command-line options. Options that
have been removed will cause the Java Virtual Machine (JVM) to exit. This check is
especially important if you use GC logging options since they have changed drastically
from Java 8. The JaCoLine tool is a good one to use to detect problems with the
command line options.

Check third-party libraries


A potential source of trouble is third-party libraries that you don't control. You can
proactively update third-party libraries to more recent versions. Or you can see what
falls out of running the application and only update those libraries that are necessary.
The problem with updating all libraries to a recent version is that it makes it harder to
find root cause if there is some error in the application. Did the error happen because of
some updated library? Or was the error caused by some change in the runtime? The
problem with updating only what's necessary is that it may take several iterations to
resolve.

The recommendation here is to make as few changes as possible and to update third-
party libraries as a separate effort. If you do update a third-party library, more often
than not you will want the latest-and-greatest version that is compatible with Java 11.
Depending on how far behind your current version is, you may want to take a more
cautious approach and upgrade to the first Java 9+ compatible version.

In addition to looking at release notes, you can use jdeps and jdeprscan to assess the jar
file. Also, the OpenJDK Quality Group maintains a Quality Outreach wiki page that lists
the status of testing of many Free Open Source Software (FOSS) projects against
versions of OpenJDK.

Explicitly set garbage collection


The Parallel garbage collector (Parallel GC) is the default GC in Java 8. If the application
is using the default, then the GC should be explicitly set with the command-line option
-XX:+UseParallelGC . The default changed in Java 9 to the Garbage First garbage

collector (G1GC). In order to make a fair comparison of an application running on Java 8


versus Java 11, the GC settings must be the same. Experimenting with the GC settings
should be deferred until the application has been validated on Java 11.

Explicitly set default options


If running on the HotSpot VM, setting the command line option -
XX:+PrintCommandLineFlags will dump the values of options set by the VM, particularly
the defaults set by the GC. Run with this flag on Java 8 and use the printed options
when running on Java 11. For the most part, the defaults are the same from 8 to 11. But
using the settings from 8 ensures parity.

Setting the command line option --illegal-access=warn is recommended. In Java 11,


using reflection to access to JDK-internal API will result in an illegal reflective access
warning. By default, the warning is only issued for the first illegal access. Setting --
illegal-access=warn will cause a warning on every illegal reflective access. You will find
more case if illegal access with the option set to warn. But you will also get a lot of
redundant warnings.
Once the application runs on Java 11, set --illegal-access=deny to mimic the future
behavior of the Java runtime. Starting with Java 16, the default will be --illegal-
access=deny .

ClassLoader cautions
In Java 8, you can cast the system class loader to a URLClassLoader . This is usually done
by applications and libraries that want to inject classes into the classpath at runtime. The
class loader hierarchy has changed in Java 11. The system class loader (also known as
the application class loader) is now an internal class. Casting to a URLClassLoader will
throw a ClassCastException at runtime. Java 11 does not have API to dynamically
augment the classpath at runtime but it can be done through reflection, with the
obvious caveats about using internal API.

In Java 11, the boot class loader only loads core modules. If you create a class loader
with a null parent, it may not find all platform classes. In Java 11, you need to pass
ClassLoader.getPlatformClassLoader() instead of null as the parent class loader in
such cases.

Locale data changes


The default source for locale data in Java 11 was changed with JEP 252 to the Unicode
Consortium's Common Locale Data Repository. This may have an impact on localized
formatting. Set the system property java.locale.providers=COMPAT,SPI to revert to the
Java 8 locale behavior, if necessary.

Potential issues
Here are some of the common issues you might come across. Follow the links for more
details about these issues.

Unrecognized VM option
Unrecognized option
VM Warning: Ignoring option
VM Warning: Option <option> was deprecated
WARNING: An illegal reflective access operation has occurred
java.lang.reflect.InaccessibleObjectException
java.lang.NoClassDefFoundError
-Xbootclasspath/p is no longer a supported option
java.lang.UnsupportedClassVersionError

Unrecognized options
If a command-line option has been removed, the application will print Unrecognized
option: or Unrecognized VM option followed by the name of the offending option. An
unrecognized option will cause the VM to exit. Options that have been deprecated, but
not removed, will produce a VM warning.

In general, options that were removed have no replacement and the only recourse is to
remove the option from the command line. The exception is options for garbage
collection logging. GC logging was reimplemented in Java 9 to use the unified JVM
logging framework . Refer to "Table 2-2 Mapping Legacy Garbage Collection Logging
Flags to the Xlog Configuration" in the section Enable Logging with the JVM Unified
Logging Framework of the Java SE 11 Tools Reference.

VM warnings
Use of deprecated options will produce a warning. An option is deprecated when it has
been replaced or is no longer useful. As with removed options, these options should be
removed from the command line. The warning VM Warning: Option <option> was
deprecated means that the option is still supported, but that support may be removed in

the future. An option that is no longer supported and will generate the warning VM
Warning: Ignoring option . Options that are no longer supported have no effect on the

runtime.

The web page VM Options Explorer provides an exhaustive list of options that have
been added to or removed from Java since JDK 7.

Error: Could not create the Java Virtual Machine

This error message is printed when the JVM encounters an unrecognized option.

WARNING: An illegal reflective access operation has occurred

When Java code uses reflection to access JDK-internal API, the runtime will issue an
illegal reflective access warning.

Console

WARNING: An illegal reflective access operation has occurred


WARNING: Illegal reflective access by my.sample.Main (file:/C:/sample/) to
method sun.nio.ch.Util.getTemporaryDirectBuffer(int)
WARNING: Please consider reporting this to the maintainers of
com.company.Main
WARNING: Use --illegal-access=warn to enable warnings of further illegal
reflective access operations
WARNING: All illegal access operations will be denied in a future release

What this means is that a module has not exported the package that is being accessed
through reflection. The package is encapsulated in the module and is, basically, internal
API. The warning can be ignored as a first effort to getting up and running on Java 11.
The Java 11 runtime permits the reflective access so that legacy code can continue to
work.

To address this warning, look for updated code that does not make use of the internal
API. If the issue cannot be resolved with updated code, either the --add-exports or the
--add-opens command-line option can be used to open access to the package. These

options allow access to unexported types of one module from another module.

The --add-exports option allows the target module to access the public types of the
named package of the source module. Sometimes code will use setAccessible(true) to
access non-public members and API. This is known as deep reflection. In this case, use --
add-opens to give your code access to the non-public members of a package. If you
are unsure whether to use --add-exports or --add-opens, start with --add-exports.
The --add-exports or --add-opens options should be considered as a work-around, not
a long-term solution. Using these options breaks encapsulation of the module system,
which is meant to keep JDK-internal API from being used. If the internal API is removed
or changes, the application will fail. Reflective access will be denied in Java 16, except
where access enabled by command line options such as --add-opens . To mimic the
future behavior, set --illegal-access=deny on the command line.

The warning in the example above is issued because the sun.nio.ch package is not
exported by the java.base module. In other words, there is no exports sun.nio.ch; in
the module-info.java file of module java.base . This can be resolved with --add-
exports=java.base/sun.nio.ch=ALL-UNNAMED . Classes that are not defined in a module

implicitly belong to the unnamed module, literally named ALL-UNNAMED .

java.lang.reflect.InaccessibleObjectException
This exception indicates that you are trying to call setAccessible(true) on a field or
method of an encapsulated class. You may also get an illegal reflective access warning.
Use the --add-opens option to give your code access to the non-public members of a
package. The exception message will tell you the module "does not open" the package
to the module that is trying to call setAccessible. If the module is "unnamed module",
use UNNAMED-MODULE as the target-module in the --add-opens option.

shell

java.lang.reflect.InaccessibleObjectException: Unable to make field private


final java.util.ArrayList jdk.internal.loader.URLClassPath.loaders
accessible:
module java.base does not "opens jdk.internal.loader" to unnamed module
@6442b0a6

$ java --add-opens=java.base/jdk.internal.loader=UNNAMED-MODULE example.Main

java.lang.NoClassDefFoundError

NoClassDefFoundError is most likely caused by a split package, or by referencing


removed modules.

NoClassDefFoundError caused by split-packages

A split package is when a package is found in more than one library. The symptom of a
split-package problem is that a class you know to be on the class-path is not found.
This issue will only occur when using the module-path. The Java module system
optimizes class lookup by restricting a package to one named module. The runtime
gives preference to the module-path over the class-path when doing a class lookup. If a
package is split between a module and the class-path, only the module is used to do the
class lookup. This can lead to NoClassDefFound errors.

An easy way to check for a split package is to plug your module path and class path into
jdeps and use the path to your application class files as the <path>. If there is a split
package, jdeps will print out a warning: Warning: split package: <package-name>
<module-path> <split-path> .

This issue can be resolved by using --patch-module <module-name>=<path>[,<path>] to


add the split package into the named module.

NoClassDefFoundError caused by using Java EE or CORBA modules

If the application runs on Java 8 but throws a java.lang.NoClassDefFoundError or a


java.lang.ClassNotFoundException , then it is likely that the application is using a

package from the Java EE or CORBA modules. These modules were deprecated in Java 9
and removed in Java 11 .

To resolve the issue, add a runtime dependency to your project.

Removed module Affected Suggested dependency


Package

Java API for XML Web Services (JAX-WS) java.xml.ws JAX WS RI Runtime

Java Architecture for XML Binding (JAXB) java.xml.bind JAXB Runtime

JavaBeans Activation Framework (JAV) java.activation JavaBeans (TM) Activation Fram


ework

Common Annotations java.xml.ws.annot Javax Annotation API


ation

Common Object Request Broker Architectu java.corba GlassFish CORBA ORB


re (CORBA)

Java Transaction API (JTA) java.transaction Java Transaction API

-Xbootclasspath/p is no longer a supported option


Support for -Xbootclasspath/p has been removed. Use --patch-module instead. The --
patch-module option is described in JEP 261 . Look for the section labeled "Patching
module content". --patch-module can be used with javac and with java to override or
augment the classes in a module.

What --patch-module does, in effect, is insert the patch module into the module
system's class lookup. The module system will grab the class from the patch module
first. This is the same effect as pre-pending the bootclasspath in Java 8.

UnsupportedClassVersionError
This exception means that you are trying to run code that was compiled with a later
version of Java on an earlier version of Java. For example, you are running on Java 11
with a jar that was compiled with JDK 13.

Java version Class file format version

8 52

9 53

10 54

11 55

12 56

13 57

Next steps
Once the application runs on Java 11, consider moving libraries off the class-path and
onto the module-path. Look for updated versions of the libraries your application
depends on. Choose modular libraries, if available. Use the module-path as much as
possible, even if you don't plan on using modules in your application. Using the
module-path has better performance for class loading than the class-path does.
Transition from Java 7 to Java 8
Article • 04/04/2023

This article provides high-level guidance on migrating your application from Java 7 to
Java 8. The usage of Java 8 features isn't covered.

There's no one-size-fits-all solution to transition code from Java 7 to Java 8. Moving


from Java 7 to Java 8 is typically a small amount of work. Potential issues include a
handful of changed APIs, tightening of type inference in javac, changes to class loaders,
and changes to permgen (part of garbage collection).

In general, the best approach is to try to run on Java 8 without recompiling first. This
approach will get your application up and running as quickly as possible. For a library,
your goal will be to publish an artifact that's compiled and tested with JDK 8.

Java 7 End of Life (EOL)


Community support will end when Java 7 reaches End Of Life on 29 July 2022. Any
applications running on Java 7 will continue to run, but Java 7 itself won't receive
updates or security patches. To minimize risk and potential security vulnerabilities,
upgrade your applications to Java 8 or 11 depending on your workload requirements.

The canonical guide to follow is the Oracle JDK Migration Guide . The migration guide
covers all of the incompatibilities in the Java specification and incompatibilities in the
JDK implementation . Most of these incompatibilities are edge cases, and you should
investigate when you see a warning or experience an error.

Running on Java 8
Most applications should run on Java 8 without modification. The first thing to try is to
run on Java 8 without recompiling the code. The point of just running is to see what
warnings and errors come out of the execution. This approach gets an
application to run on Java 8 more quickly by focusing on the minimum work that needs
to be done.

You can resolve most of the problems you may come across without having to
recompile code. If you have to fix an issue in the code, then make the fix, but continue
to compile with JDK 7. If possible, work on getting the application to run with java
version 8 before compiling with JDK 8.
Compiling with Java 8
Compiling with JDK 8 may require updates to build scripts, tools, test frameworks, and
included libraries. Use the -Xlint:unchecked option for javac to get the details on the
use of JDK internal API and other warnings.

Migration off Java 7 for Azure App Service


To migrate your App Services from Java 7 to Java 8 or 11, sign in to Azure portal,
navigate to the web app(s) you want to update, then go to Configuration > Settings >
Stack Settings. You'll see dropdowns for the Java major and minor versions, and the
Tomcat version if you're using Tomcat. Select Java 8 or 11. Remember, you can make this
configuration change in a deployment slot to safely test the configuration change, then
swap the new environment into production. (Java 7 may be hidden to keep customers
from taking dependencies on old runtimes.) For more information, see Set up staging
environments in Azure App Service.

You can use the JAVA_TOOLS app setting if you need to specify any new runtime options,
and they'll be applied when your application starts. For more information, see Configure
a Java app for Azure App Service. For more information about support policies for
runtimes on App Service, see the Built-in languages and frameworks section of the App
Service overview.

Next steps
After you get your application to run on Java 8, we recommend following the Java
modernization path to Java 11 using the following guides.

Reasons to move to Java 11.


Transition from Java 8 to Java 11.
Monitor and manage Java workloads
with JDK Flight Recorder and Mission
Control
Article • 04/04/2023

This article shows you how to monitor and manage Java workloads with JDK Flight
Recorder and JDK Mission Control.

Oracle open-sourced Mission Control in 2018, and it's managed as a project under the
OpenJDK umbrella. Coupled with Flight Recorder, Mission Control delivers low-
overhead, interactive monitoring and management capabilities for Java workloads.

Install JDK Mission Control and connect to a


JVM
Follow the steps below to install JDK Mission Control, connect to a Java Virtual Machine
(JVM), and gain real-time visibility into all aspects of a running application.

1. Make sure you have a JDK installed.

2. Find a JDK Mission Control binary from the OpenJDK JMC Project on GitHub .
Then, choose the appropriate version for your system, save it locally, and change
to that directory.

3. Expand the downloaded file. The examples below are for Azul Zulu Mission
Control .

Linux:

Bash

tar -xzvf zmc8.0.0.17-ca-linux_x64.tar.gz

Windows:

PowerShell

unzip -zxvf zmc8.0.0.17-ca-win_x64.zip

macOS:
Bash

tar -xzvf zmc8.0.0.17-ca-macos_x64.tar.gz

4. Start your Java application using one of the compatible JDKs. For example:

Azure CLI

$JAVA_HOME/bin/java -jar MyApplication.jar

5. Start Zulu Mission Control

Linux:

Azure CLI

zmc8.0.0.17-ca-linux_x64/zmc

Windows:

Azure CLI

zmc8.0.0.17-ca-win_x64\zmc.exe

macOS:

Azure CLI

zmc8.0.0.17-ca-macos_x64/Zulu\ Mission\ Control.app/Contents/MacOS/zmc

6. Locate the JVM running your application.

a. In the upper left pane of the Zulu Mission Control window, select the tab
labeled JVM Browser.

b. Select and expand the list item in the upper left for the JVM instance running
your application.
7. Start a Flight Recording, if necessary.

a. If the Flight Recorder displays "No Recordings", start one. To start a recording,
right-click on the Flight Recorder line in the JVM Browser tab and then select
Start Flight Recording.

b. Select either a fixed duration recording or a continuous recording, and either a


Profiling configuration (fine-grained) or a Continuous configuration (lower
overhead), then select Finish.
8. Dump the Flight Recording.

a. A Flight Recording should appear below the Flight Recorder line in the JVM
Browser. Right-click on the line representing the Flight Recording and select
Dump whole recording.

b. A new tab will appear in the large pane on the right side of the Zulu Mission
Control window. This pane represents the Flight Recording just dumped from
the JVM running your application.

9. Examine the Flight Recording using Zulu Mission Control


a. If not already activated, select the tab labeled Outline in the left pane of the
Zulu Mission Control Window. This tab contains different views of the data
collected in the Flight Recording.
Resources
Azul Systems provides a demonstration video narrated by Azul Systems Deputy CTO
Simon Ritter. The video walks you through the configuration and setup of both Flight
Recorder and Zulu Mission Control. The Flight Recorder discussion starts at 31:30.
Configure timezones in Java
Article • 01/08/2025

You can configure timezones in Java through various methods, enabling applications to
operate in the desired timezone context. Two common approaches are setting the TZ
environment variable and specifying the JVM property -Duser.timezone . This article
provides a brief overview of both methods.

Setting the TZ environment variable


The TZ environment variable is a standard way to set the timezone for applications
running on Unix-like operating systems. When you set this variable, the Java Virtual
Machine (JVM) picks up the timezone setting during startup.

Set the TZ environment variable at the OS level


Use the following steps to set the TZ environment variable at the operating system
level:

1. Identify the desired timezone. Timezones are typically specified in the


"Area/Location" format, such as "America/New_York" or "Europe/London".

2. Set the TZ environment variable using one of the following methods:

On Unix/Linux systems, use the following command to set the variable in the
terminal or in your shell configuration file - .bashrc , .bash_profile , .zshrc ,
and so on:

Bash

export TZ=America/New_York

On Windows systems, use the following command to set the variable in the
command prompt or through system environment settings:

Windows Command Prompt

set TZ=America/New_York

3. Restart the application so that the JVM can pick up the new timezone setting.
Example
In the following example, the application myapp.jar runs in the Europe/London timezone:

sh

export TZ=Europe/London
java -jar myapp.jar

Setting the TZ environment variable in a Dockerfile


When you run Java applications in containers, you can set the TZ environment variable
within the Dockerfile to ensure that the container runs in the desired timezone.

Dockerfile example
The following example configures the container to use the America/New_York timezone
by setting the TZ environment variable and installing the tzdata package:

Dockerfile

# Use a base image with Java installed


FROM mcr.microsoft.com/openjdk/jdk:21-mariner

# Set the timezone environment variable


ENV TZ=America/New_York

# Set the working directory


WORKDIR /app

# Copy the application JAR file to the container


COPY myapp.jar /app/myapp.jar

# Run the application


CMD ["java", "-jar", "myapp.jar"]

Setting the JVM property -Duser.timezone


Another method to configure the timezone in Java is to specify the -Duser.timezone
property when starting the JVM. This method is platform-independent and enables
setting the timezone directly from the command line or within application scripts. This
JVM property takes precedence over the environment variable TZ .

Use the following steps to set the -Duser.timezone property:


1. Identify the desired timezone. Similar to the TZ environment variable, the
timezone is specified in the "Area/Location" format.

2. Set the -Duser.timezone property by adding it to the Java command line when
starting the application, as shown in the following example:

Bash

java -Duser.timezone=America/New_York -jar myapp.jar

Example
In the following example, the application myapp.jar runs in the Asia/Tokyo timezone:

Bash

java -Duser.timezone=Asia/Tokyo -jar myapp.jar

Other systems and environments


You can apply the principles of configuring timezones in Java using the TZ environment
variable and the -Duser.timezone JVM property to other systems and environments.
Whether you run applications on cloud platforms, within virtual machines (VMs), or in
various container orchestration systems, you can use the same methods to ensure that
your Java applications operate in the correct timezone context.

On cloud platforms, configure the TZ environment variable or JVM property within your
deployment scripts or environment configuration settings.

On virtual machines, set the TZ environment variable in your VM's environment or use
the JVM property in your application startup scripts.

With container orchestration, use the Dockerfile example for containerized applications,
ensuring that the timezone data is available and correctly set.

By following these principles, you can achieve consistent timezone configuration across
different deployment environments for your Java applications.
Java Security and Cryptography
Article • 04/04/2023

Re-enable TLSv1 and TLSv1.1


Some legacy systems may still be tied to the older, insecure TLSv1 and TLSv1.1
protocols. Starting with OpenJDK 11.0.11, these protocol versions are disabled by
default.

To re-enable, users must perform these steps:

1. In the installation directory of the JDK, navigate to the folder ./conf/security/


2. Open the file java.security
3. Search for the configuration property jdk.tls.disabledAlgorithms
4. Remove the elements TLSv1 and/or TLSv1.1
5. Relaunch the Java application

JCE Provider for JCA and Crypto


javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Applications that need to establish secure connections (e.g., HTTPS, SFTP, etc) must run
on a Java runtime with a compatible security provider for the Java Cryptography
Architecture (JCA). The OpenJDK project contains a default implementation provider -
the Java Cryptography Extension (JCE) - in the jdk.crypto.ec .

If your application requires establishing secure connections, make sure the module
jdk.crypto.ec is included in the assembled Java runtime, or that a 3rd-party provider
(e.g., BouncyCastle ) is included.
Support roadmap for the Microsoft
Build of OpenJDK
Article • 11/15/2024

This article describes the support policy and roadmap for the Microsoft Build of
OpenJDK binaries.

OpenJDK is the open source reference implementation of the Java SE Platform


(Language and Virtual Machine) , with its upstream project governed by Oracle
Corporation at openjdk.java.net and with source code available at
github.com/openjdk . The project is released under the GNU General Public License
version 2 with Classpath Exception (GPLv2+CE ). Java and OpenJDK are trademarks of
Oracle Corporation.

The Microsoft Build of OpenJDK refers to a binary, or binaries, of the OpenJDK project
that are compiled, packaged, and tested by Microsoft. Long-Term Support (LTS) releases
of the Microsoft Build of OpenJDK are also tested against the Oracle’s Java Technology
Compatibility Kit (TCK).

Support policy
This support policy applies to Long-Term Support (LTS) releases of the Microsoft Build of
OpenJDK. The LTS releases of Microsoft Build of OpenJDK will receive quarterly updates,
available through microsoft.com/openjdk . Access to quarterly updates of Microsoft
Builds of OpenJDK are free of charge and available to anyone, and can be deployed
anywhere as per the license of the software.

Microsoft Build of OpenJDK binaries may contain new or backported fixes, security fixes,
and enhancements that we deem important to our customers and our internal users.
Certain changes may have not been (and may not ever be) incorporated in the upstream
OpenJDK project due to decisions outside of Microsoft’s control. Fixes, security fixes,
and enhancements that have not yet been formally upstreamed will be clearly
signposted in our release notes, with source code available.

Commercial support
Commercial support is only available for Microsoft Azure customers with active Azure
Support Plans and only covers Java workloads deployed to Azure and Azure Stack
services, and Azure Arc clusters. If you have an issue with the Microsoft Build of
OpenJDK within an Azure environment, please submit a support request .
Microsoft Build of OpenJDK commercial support follows Microsoft's Modern Lifecycle
Policy.

Community support
For all other scenarios, users of Microsoft Build of OpenJDK, including LTS and non-LTS
releases are welcome to raise issues, provide feedback, and start discussions at
github.com/microsoft/openjdk .

Release and servicing roadmap


The OpenJDK project releases new versions of Java every 6 months. Vendors of
OpenJDK binaries provide different support timelines for different versions of OpenJDK.
Microsoft's support timeline for LTS releases of this build are described below.

The following table shows the support roadmap for the existing LTS releases of
Microsoft Build of OpenJDK.

ノ Expand table

Version Microsoft Build of OpenJDK OpenJDK release Earliest end-of-


release date date support date

OpenJDK 11 May, 2021 September, 2018 September, 2027


LTS

OpenJDK 17 September, 2021 September, 2021 September, 2027


LTS

OpenJDK 21 September, 2023 September, 2023 September, 2028


LTS

Within a release's support lifecycle, systems must remain current on the latest update to
receive commercial support. Updates for Microsoft Builds of OpenJDK are released every
quarter: January, April, July, and October.

The earliest end-of-support dates published above are initial targets. Microsoft may
extend support for its LTS releases.

For more information, see the Modern Lifecycle Policy.

System requirements
The following table shows the certified hardware architectures for the LTS releases of
Microsoft Build of OpenJDK.

ノ Expand table

Version Architecture Linux macOS Windows Alpine (musl)

OpenJDK 11 LTS x64 Yes Yes Yes Yes

AArch64 Yes Yes Yes No

OpenJDK 17 LTS x64 Yes Yes Yes Yes

AArch64 Yes Yes Yes No

OpenJDK 21 LTS x64 Yes Yes Yes No

AArch64 Yes Yes Yes No

Operating systems and Linux distributions


Microsoft Build of OpenJDK is available for Linux, Windows, and macOS, on up-to-date
and actively maintained versions of these operating systems and/or their distributions,
for as long as they are continually receiving security fixes.

Other versions and releases


Microsoft may release binaries of Microsoft Build of OpenJDK for other versions of
OpenJDK – besides the ones listed above – without Long-Term Support. Microsoft will
not provide commercial support for non-LTS releases, and reserves the right to not
provide quarterly updates for non-LTS releases.

Java 8
A limited set of Azure services may offer a runtime for Java 8, or run on Java 8. In these
scenarios, Microsoft relies on Eclipse Temurin builds of OpenJDK for Java 8. Customers
willing to build and deploy Java 8 applications on Azure are encouraged to download
binaries directly from the Eclipse Adoptium website . Microsoft is committed to
continue collaborating in the Eclipse Adoptium working group for the foreseable
future. For more information on the support timeline, see the Eclipse Adoptium
Support documentation.
Release notes for the Microsoft Build of
OpenJDK
Article • 01/22/2025

This article lists the fixes contained in the releases of Microsoft Build of OpenJDK
packages and the Microsoft-specific enhancements pending to be merged upstream.

Known Issues

OpenJDK 17
When running Alpine x64 (musl) builds on Alpine Linux 3.19.0 or later,
SecureDirectoryStream is not supported.

OpenJDK 11
When running Alpine x64 (musl) builds on Alpine Linux 3.19.0 or later,
SecureDirectoryStream is not supported.

OpenJDK 21

OpenJDK 21.0.6
releases/jdk-21.0.6
List of fixes
See the OpenJDK Vulnerability Advisory for vulnerabilities that were fixed in this
release.

Enhancements / Additional Fixes

Backport of JDK-8338136 : Hotspot should support multiple large page sizes on


Windows
Backport of JDK-8345296 : AArch64: VM crashes with SIGILL when prctl is
disallowed
Backport of JDK-8335977 : Deoptimization fails with assert "object should be
reallocated already"
Backport of JDK-8340454 : C2 EA asserts with "previous reducible Phi is no longer
reducible before SUT"

OpenJDK 21.0.5
releases/jdk-21.0.5
List of fixes
See the OpenJDK Vulnerability Advisory for vulnerabilities that were fixed in this
release.

Enhancements

Removed calls to undocumented Windows APIs (NtCreateKeyedEvent,


NtReleaseKeyedEvent, NtWaitForKeyedEvent).
Backport of JDK-8334475 : UnsafeIntrinsicsTest.java#ZGenerationalDebug
assert(!assert_on_failure) failed: Has low-order bits set.

OpenJDK 21.0.4
releases/jdk-21.0.4
List of fixes

Enhancements

Enables Hotspot to use processors across all Windows processor groups on


Windows 11/Windows Server 2022 and later.

OpenJDK 21.0.3
releases/jdk-21.0.3
List of fixes

Enhancements

Includes a new feature (see JDK-8287061 and JDK-8289943 ) to improve the


performance of Escape Analysis by increasing the number of opportunities for
Scalar Replacement. This feature is enabled by default. To disable it, developers
must use the following JVM flags:

-XX:+UnlockDiagnosticVMOptions -XX:-ReduceAllocationMerges
Includes a new JFR event to track Compiler Queue Utilization (a backport of JDK-
8317562 ).

OpenJDK 21.0.2
releases/jdk-21.0.2
List of fixes

Enhancements

Includes a new feature (see JDK-8287061 and JDK-8289943 ) to improve the


performance of Escape Analysis by increasing the number of opportunities for
Scalar Replacement. This feature is enabled by default. To disable it, developers
must use the following JVM flags:

-XX:+UnlockDiagnosticVMOptions -XX:-ReduceAllocationMerges

Includes a new JFR event to track Compiler Queue Utilization (a backport of JDK-
8317562 ).

OpenJDK 21.0.1
releases/jdk-21.0.1
List of fixes

Enhancements
Includes a new feature (see JDK-8287061 and JDK-8289943 ) to improve the
performance of Escape Analysis by increasing the number of opportunities for
Scalar Replacement. This feature is enabled by default. To disable it, developers
must use the following JVM flags:

-XX:+UnlockDiagnosticVMOptions -XX:-ReduceAllocationMerges

Known issues

AArch64 binaries do not have Default CDS (JEP 341 ) archives. Run java -
Xshare:dump to produce them after installation.

OpenJDK 21.0.0
releases/jdk-21.0.0
List of fixes

Enhancements

Includes a new feature (see JDK-8287061 and JDK-8289943 ) to improve the


performance of Escape Analysis by increasing the number of opportunities for
Scalar Replacement. This feature is enabled by default. To disable it, developers
must use the following JVM flags:

-XX:+UnlockDiagnosticVMOptions -XX:-ReduceAllocationMerges

Known issues
AArch64 binaries do not have Default CDS (JEP 341 ) archives. Run java -
Xshare:dump to produce them after installation.

OpenJDK 17

OpenJDK 17.0.14
releases/jdk-17.0.14
List of fixes
See the OpenJDK Vulnerability Advisory for vulnerabilities that were fixed in this
release.

Enhancements / Additional Fixes

Backport of JDK-8338136 : Hotspot should support multiple large page sizes on


Windows
Backport of JDK-8345296 : AArch64: VM crashes with SIGILL when prctl is
disallowed
Backport of JDK-8335977 : Deoptimization fails with assert "object should be
reallocated already"
Backport of JDK-8340454 : C2 EA asserts with "previous reducible Phi is no longer
reducible before SUT"

OpenJDK 17.0.13
releases/jdk-17.0.13
List of fixes
See the OpenJDK Vulnerability Advisory for vulnerabilities that were fixed in this
release.

Enhancements
Removed calls to undocumented Windows APIs (NtCreateKeyedEvent,
NtReleaseKeyedEvent, NtWaitForKeyedEvent).

OpenJDK 17.0.12
releases/jdk-17.0.12
List of fixes

Enhancements
Enables Hotspot to use processors across all Windows processor groups on
Windows 11/Windows Server 2022 and later.
Disable G1 preventive collections by default.

OpenJDK 17.0.11
releases/jdk-17.0.11
List of fixes

Enhancements
Includes a new feature (see JDK-8287061 and JDK-8289943 ) to improve the
performance of Escape Analysis by increasing the number of opportunities for
Scalar Replacement. This feature is enabled by default. To disable it, developers
must use the following JVM flags:

-XX:+UnlockDiagnosticVMOptions -XX:-ReduceAllocationMerges

Added support for SST files as KeyStores on Windows (see JDK-8306688 ), which
can be enabled by using the following property:

-Dsun.security.mscapi.enableSST=true

OpenJDK 17.0.10
releases/jdk-17.0.10
List of fixes

Enhancements

Includes a new feature (see JDK-8287061 and JDK-8289943 ) to improve the


performance of Escape Analysis by increasing the number of opportunities for
Scalar Replacement. This feature is enabled by default. To disable it, developers
must use the following JVM flags:

-XX:+UnlockDiagnosticVMOptions -XX:-ReduceAllocationMerges

Added support for SST files as KeyStores on Windows (see JDK-8306688 ), which
can be enabled by using the following property:

-Dsun.security.mscapi.enableSST=true

OpenJDK 17.0.9
releases/jdk-17.0.9
List of fixes

Enhancements
Includes a new feature (see JDK-8287061 and JDK-8289943 ) to improve the
performance of Escape Analysis by increasing the number of opportunities for
Scalar Replacement. This feature is enabled by default. To disable it, developers
must use the following JVM flags:

-XX:+UnlockDiagnosticVMOptions -XX:-ReduceAllocationMerges

Added support for SST files as KeyStores on Windows (see JDK-8306688 ), which
can be enabled by using the following property:

-Dsun.security.mscapi.enableSST=true

Backport of JDK-8303607 SunMSCAPI provider leaks memory and keys

Known issues

AArch64 binaries do not have Default CDS (JEP 341 ) archives. Run java -
Xshare:dump to produce them after installation.
OpenJDK 17.0.8
releases/jdk-17.0.8
List of fixes

Enhancements

Includes a new feature (see JDK-8287061 and JDK-8289943 ) to improve the


performance of Escape Analysis by increasing the number of opportunities for
Scalar Replacement. This feature is now enabled by default. To disable it,
developers must use the following JVM flag:

-XX:-ReduceAllocationMerges

Known issues
AArch64 binaries do not have Default CDS (JEP 341 ) archives. Run java -
Xshare:dump to produce them after installation.

OpenJDK 17.0.7
releases/jdk-17.0.7
List of fixes

Enhancements

Includes an experimental feature to improve the performance of Escape Analysis


by increasing the number of opportunities for Scalar Replacement. To enable this
feature, developers must use the following JVM flags:

-XX:+UnlockExperimentalVMOptions -XX:+ReduceAllocationMerges

Known issues

AArch64 binaries do not have Default CDS (JEP 341 ) archives. Run java -
Xshare:dump to produce them after installation.

OpenJDK 17.0.6
releases/jdk-17.0.6
List of fixes

Enhancements
Includes an experimental feature to improve the performance of Escape Analysis
by increasing the number of opportunities for Scalar Replacement. To enable this
feature, developers must use the following JVM flags:

-XX:+UnlockExperimentalVMOptions -XX:+ReduceAllocationMerges

Known issues

Binaries do not have Default CDS (JEP 341 ) archives. Run java -Xshare:dump to
produce them after installation.

OpenJDK 17.0.5
releases/jdk-17.0.5
List of fixes

Enhancements

Added an experimental feature to improve the performance of Escape Analysis by


increasing the number of opportunities for Scalar Replacement. To enable this
feature, developers must use the following JVM flags:

-XX:+UnlockExperimentalVMOptions -XX:+ReduceAllocationMerges

Known issues

Binaries do not have Default CDS (JEP 341 ) archives. Run java -Xshare:dump to
produce them after installation.

OpenJDK 17.0.4.1
jdk-17.0.4.1-ga@02fa4be
List of fixes

Known issues
Binaries do not have Default CDS (JEP 341 ) archives. Run java -Xshare:dump to
produce them after installation.

OpenJDK 17.0.4
jdk-17.0.4-ga@c53d022
List of fixes

Known issues

Binaries do not have Default CDS (JEP 341 ) archives. Run java -Xshare:dump to
produce them after installation.

OpenJDK 17.0.3
jdk-17.0.3-ga@c1a8749
List of fixes

Known issues

Binaries do not have Default CDS (JEP 341 ) archives. Run java -Xshare:dump to
produce them after installation.

OpenJDK 17.0.2
jdk-17.0.2-ga@6f0f426
List of fixes

Known issues
Binaries do not have Default CDS (JEP 341 ) archives. Run java -Xshare:dump to
produce them after installation.
RPM package may not update automatically. Run yum install msopenjdk-17-
17.0.2+8_LTS-1 to force update to latest release.

OpenJDK 17.0.1
jdk-17.0.1-ga@75240a5
List of fixes
Known issues
Binaries for AArch64 do not have Default CDS (JEP 341 ) archives. Run java -
Xshare:dump to produce them after installation.

RPM package may not update automatically. Run yum install msopenjdk-17-
17.0.1+12_LTS-1 to force update to latest release.

OpenJDK 17.0.0
jdk-17-ga@dfacda48
List of fixes

OpenJDK 11

OpenJDK 11.0.26
release/jdk-11.0.26
List of fixes
See the OpenJDK Vulnerability Advisory for vulnerabilities that were fixed in this
release.

Enhancements / Additional Fixes


Backport of JDK-8335977 : Deoptimization fails with assert "object should be
reallocated already"
Backport of JDK-8340454 : C2 EA asserts with "previous reducible Phi is no longer
reducible before SUT"

OpenJDK 11.0.25
release/jdk-11.0.25
List of fixes
See the OpenJDK Vulnerability Advisory for vulnerabilities that were fixed in this
release.

Enhancements
Enables Hotspot to use processors across all Windows processor groups on
Windows 11/Windows Server 2022 and later.
OpenJDK 11.0.24
release/jdk-11.0.24
List of fixes

Enhancements

Enables Hotspot to use processors across all Windows processor groups on


Windows 11/Windows Server 2022 and later.

OpenJDK 11.0.23
release/jdk-11.0.23
List of fixes

Enhancements
Includes a new feature (see JDK-8287061 and JDK-8289943 ) to improve the
performance of Escape Analysis by increasing the number of opportunities for
Scalar Replacement. This feature is enabled by default. To disable it, developers
must use the following JVM flags:

-XX:+UnlockDiagnosticVMOptions -XX:-ReduceAllocationMerges

Added support for SST files as KeyStores on Windows (see JDK-8306688 ), which
can be enabled by using the following property:

-Dsun.security.mscapi.enableSST=true

Backports of the following enhancements and bug fixes:


JDK-8250902 Implement MD5 Intrinsics on x86 - Java Bug System
JDK Flight Recorder
JDK-8226897 Provide object age with JFR OldObjectSample event
JDK-8232594 Make the output of the JFR command duration more user
friendly
JDK-8216041 Event Request Deoptimization
JDK-8216995 Clean up JFR Command Line
JDK-8217089 Lazy install os interface components for improved startup

Known issues
Binaries for macOS/AArch64 do not have Default CDS (JEP 341 ) archives. Run
java -Xshare:dump to produce them after installation.

OpenJDK 11.0.22
release/jdk-11.0.22
List of fixes

Enhancements

Includes a new feature (see JDK-8287061 and JDK-8289943 ) to improve the


performance of Escape Analysis by increasing the number of opportunities for
Scalar Replacement. This feature is enabled by default. To disable it, developers
must use the following JVM flags:

-XX:+UnlockDiagnosticVMOptions -XX:-ReduceAllocationMerges

Added support for SST files as KeyStores on Windows (see JDK-8306688 ), which
can be enabled by using the following property:

-Dsun.security.mscapi.enableSST=true

Backports of the following enhancements and bug fixes:


JDK-8250902 Implement MD5 Intrinsics on x86 - Java Bug System
JDK Flight Recorder
JDK-8226897 Provide object age with JFR OldObjectSample event
JDK-8232594 Make the output of the JFR command duration more user
friendly
JDK-8216041 Event Request Deoptimization
JDK-8216995 Clean up JFR Command Line
JDK-8217089 Lazy install os interface components for improved startup

Known issues
Binaries for macOS/AArch64 do not have Default CDS (JEP 341 ) archives. Run
java -Xshare:dump to produce them after installation.

OpenJDK 11.0.21
release/jdk-11.0.21
List of fixes
Enhancements
Includes a new feature (see JDK-8287061 and JDK-8289943 ) to improve the
performance of Escape Analysis by increasing the number of opportunities for
Scalar Replacement. This feature is enabled by default. To disable it, developers
must use the following JVM flags:

-XX:+UnlockDiagnosticVMOptions -XX:-ReduceAllocationMerges

Added support for SST files as KeyStores on Windows (see JDK-8306688 ), which
can be enabled by using the following property:

-Dsun.security.mscapi.enableSST=true

Backports of the following enhancements and bug fixes:


JDK-8250902 Implement MD5 Intrinsics on x86 - Java Bug System
JDK Flight Recorder
JDK-8226897 Provide object age with JFR OldObjectSample event
JDK-8232594 Make the output of the JFR command duration more user
friendly
JDK-8216041 Event Request Deoptimization
JDK-8216995 Clean up JFR Command Line
JDK-8217089 Lazy install os interface components for improved startup
JDK-8303607 SunMSCAPI provider leaks memory and keys

Known issues

Binaries for AArch64 do not have Default CDS (JEP 341 ) archives. Run java -
Xshare:dump to produce them after installation.

OpenJDK 11.0.20.1
release/jdk-11.0.20.1
List of fixes

Enhancements
Includes a new feature (see JDK-8287061 and JDK-8289943 ) to improve the
performance of Escape Analysis by increasing the number of opportunities for
Scalar Replacement. This feature is enabled by default. To disable it, developers
must use the following JVM flag:
-XX:-ReduceAllocationMerges

Backports of the following enhancements and bug fixes:


JDK-8250902 Implement MD5 Intrinsics on x86 - Java Bug System
JDK Flight Recorder
JDK-8226897 Provide object age with JFR OldObjectSample event
JDK-8232594 Make the output of the JFR command duration more user
friendly
JDK-8216041 Event Request Deoptimization
JDK-8216995 Clean up JFR Command Line
JDK-8217089 Lazy install os interface components for improved startup

Known issues
Binaries for AArch64 do not have Default CDS (JEP 341 ) archives. Run java -
Xshare:dump to produce them after installation.

OpenJDK 11.0.20
release/jdk-11.0.20
List of fixes

Enhancements
Includes a new feature (see JDK-8287061 and JDK-8289943 ) to improve the
performance of Escape Analysis by increasing the number of opportunities for
Scalar Replacement. This feature is now enabled by default. To disable it,
developers must use the following JVM flag:

-XX:-ReduceAllocationMerges

Backports of the following enhancements and bug fixes:


JDK-8250902 Implement MD5 Intrinsics on x86 - Java Bug System
JDK Flight Recorder
JDK-8226897 Provide object age with JFR OldObjectSample event
JDK-8232594 Make the output of the JFR command duration more user
friendly
JDK-8216041 Event Request Deoptimization
JDK-8216995 Clean up JFR Command Line
JDK-8217089 Lazy install os interface components for improved startup
Known issues
Binaries for AArch64 do not have Default CDS (JEP 341 ) archives. Run java -
Xshare:dump to produce them after installation.

OpenJDK 11.0.19
release/jdk-11.0.19
List of fixes

Enhancements
Includes an experimental feature to improve the performance of Escape Analysis
by increasing the number of opportunities for Scalar Replacement. To enable this
feature, developers must use the following JVM flags:

-XX:+UnlockExperimentalVMOptions -XX:+ReduceAllocationMerges

Backports of the following enhancements and bug fixes:


JDK-8250902 Implement MD5 Intrinsics on x86 - Java Bug System
JFR
JDK-8226897 Provide object age with JFR OldObjectSample event - Java
Bug System
JDK-8232594 Make the output of the JFR command duration more user
friendly - Java Bug System
JDK-8216041 [Event Request] - Deoptimization - Java Bug System

Known issues

Binaries for AArch64 do not have Default CDS (JEP 341 ) archives. Run java -
Xshare:dump to produce them after installation.

OpenJDK 11.0.18
release/jdk-11.0.18
List of fixes

Enhancements

Includes an experimental feature to improve the performance of Escape Analysis


by increasing the number of opportunities for Scalar Replacement. To enable this
feature, developers must use the following JVM flags:

-XX:+UnlockExperimentalVMOptions -XX:+ReduceAllocationMerges

Backports of the following enhancements and bug fixes:


JDK-8250902 Implement MD5 Intrinsics on x86 - Java Bug System
JFR
JDK-8226897 Provide object age with JFR OldObjectSample event - Java
Bug System
JDK-8232594 Make the output of the JFR command duration more user
friendly - Java Bug System
JDK-8216041 [Event Request] - Deoptimization - Java Bug System

Known issues
Binaries do not have Default CDS (JEP 341 ) archives. Run java -Xshare:dump to
produce them after installation.

OpenJDK 11.0.17
release/jdk-11.0.17
List of fixes

Enhancements
Added an experimental feature to improve the performance of Escape Analysis by
increasing the number of opportunities for Scalar Replacement. To enable this
feature, developers must use the following JVM flags:

-XX:+UnlockExperimentalVMOptions -XX:+ReduceAllocationMerges

Known issues
Binaries do not have Default CDS (JEP 341 ) archives. Run java -Xshare:dump to
produce them after installation.

OpenJDK 11.0.16.1
jdk-11.0.16.1-ga@63e4b5c
List of fixes
Known issues
Binaries do not have Default CDS (JEP 341 ) archives. Run java -Xshare:dump to
produce them after installation.

OpenJDK 11.0.16
jdk-11.0.16-ga@224e1a3
List of fixes

Known issues
Binaries do not have Default CDS (JEP 341 ) archives. Run java -Xshare:dump to
produce them after installation.

OpenJDK 11.0.15
jdk-11.0.15-ga@224e1a3
List of fixes

Known issues
Binaries do not have Default CDS (JEP 341 ) archives. Run java -Xshare:dump to
produce them after installation.

OpenJDK 11.0.14.1
jdk-11.0.14.1-ga@b8cdf1a
List of fixes

Enhancements

Backport of JEP 391 macOS/AArch64 Port


Backport of JEP 386 Alpine Linux Port

Known issues
Binaries do not have Default CDS (JEP 341 ) archives. Run java -Xshare:dump to
produce them after installation.
OpenJDK 11.0.14
jdk-11.0.14-ga@1453335
List of fixes

Enhancements

Backport of JEP 391 macOS/AArch64 Port


Backport of JEP 386 Alpine Linux Port

Known issues
Binaries do not have Default CDS (JEP 341 ) archives. Run java -Xshare:dump to
produce them after installation.

OpenJDK 11.0.13
jdk-11.0.13-ga@71f2c751
List of fixes

OpenJDK 11.0.12
jdk-11.0.12-ga@d1541f3
List of fixes

Enhancements
JDK-8250902 Implement MD5 Intrinsics on x86 - Java Bug System
Backports of the following enhancements and bug fixes:
https://openjdk.java.net/jeps/388
https://github.com/openjdk/jdk/pull/212
Backport of AArch64: initialize memory allocated for locals according to
Windows AArch64 stack page growth requirement in template interpreter :
JDK-8269391
Backport of AArch64: Fix MacroAssembler::get_thread convention : JDK-
8271002
Backport of C4530 was reported from VS 2019 at access bridge : JDK-8271095
Backport of JVMCI: Enable it for Windows+AArch64 : JDK-8264184

OpenJDK 11.0.11
List of security fixes and other fixes in OpenJDK 11.0.11

Enhancements
JDK-8250902 Implement MD5 Intrinsics on x86 - Java Bug System

Provide feedback on the Microsoft Build of


OpenJDK
Send us your comments, thoughts, and ideas to help us improve the Microsoft Build of
OpenJDK. Visit our OpenJDK discussions page on GitHub to send us your feedback.

Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

Other releases

OpenJDK 16.0.2
jdk-16.0.2-ga@3b56f0b
List of fixes

Enhancements

JDK-8269392 : Backport of AArch64: initialize memory allocated for locals


according to Windows AArch64 stack page growth requirement in template
interpreter
Backports of JEP 391: macOS/AArch64 Port , PR: 8253795: Implementation of JEP
391: macOS/AArch64 Port with these additional bug fixes:
JDK-8271576 : Backport of Arch64: Fix MacroAssembler::get_thread
convention
JDK-8271577 : Backport of [macos_aarch64] Crash in jni_fast_GetLongField
JNF removal and dependency fixups: Backports of Bad JNI lookup
getFocusOwner in accessibility code on Mac OS X , [macOS] Bad JNI lookup
error : Accessible actions do not work on macOS , Remove JNF dependency
from libsaproc/MacosxDebuggerLocal.m and [macOS] Incorrect JNI
parameters in number conversion in A11Y code
SIGBUS fix and a few others: Backports of [macos_aarch64] SIGBUS in
Assembler::ld_st2 , Missed JNFInstanceOf -> IsInstanceOf conversion ,
AArch64: Refactor interpreter native wrappers , Use MAP_JIT when allocating
pages for code cache on macOS , Create stubRoutines.inline.hpp with
SafeFetch implementation
Frequently asked questions
Article • 04/04/2023

1. For how long will you support each release of the Microsoft Build of OpenJDK?

See the Support page for details.

2. Will you release other versions of OpenJDK?

We plan to release OpenJDK binaries for versions where there is mutual LTS
consensus across OpenJDK contributors and vendors.

3. Will you release binaries of OpenJDK 8?

On Azure-managed services that offer Java 8 as a target runtime option,


Microsoft may rely on third party binaries such as Eclipse Adoptium . For all
other Azure services, customers can bring their JDK of choice for Java 8 from
3rd-party vendors. However, Microsoft recommends that customers move to
Java 17 and later versions to benefit from several enhancements that can be
translated into cost savings in cloud deployments and accelerated developer
productivity. We believe the process is worth the effort and have provided
guidance to help streamline this transition.
For more information on JDK versions supported across Azure services, see
Java Support on Azure and Azure Stack.

4. How are these binaries licensed?

General Public License 2.0 with Classpath Exception (GPLv2+CE).

5. How long will it take to get binaries after OpenJDK has declared the GA tag?

Microsoft Build of OpenJDK is put through a rigorous suite of tests from the
Eclipse Adoptium AQAvit project as well as the compliance tests from the
Java Technology Compatibility Kit. This process typically takes 24-48 hours to
complete but can take longer.

6. Will Microsoft release out-of-band fixes due to critical or security vulnerabilities?

Only in extreme circumstances where other vendors also produce out-of-


band patches for global scale security vulnerabilities. The likelihood of this
happening is extremely low. Security vulnerabilities are often treated in
secrecy, even for an open source project like OpenJDK. For more information,
see OpenJDK Vulnerabilities Group .
7. What happens if I find a bug in Microsoft Build of OpenJDK?

If an Azure customer identifies a problem first-hand with the Microsoft Build


of OpenJDK, but it's not a security flaw that imposes risk, we'll prioritize the
fixing of this issue and release it for the next quarterly update. We'll upstream
the fix as soon as possible so it can also be addressed in other versions of
Java that may be impacted, and be available in other OpenJDK distributions.
If you're not an Azure customer, report the issue to our GitHub repository at
microsoft/openjdk .
If it's a security issue, we'll work to validate it, and then report it to the
OpenJDK Vulnerability Group.

Provide feedback on the Microsoft Build of


OpenJDK
Send us your comments, thoughts, and ideas to help us improve the Microsoft Build of
OpenJDK. Visit our OpenJDK discussions page on GitHub to send us your feedback.

Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

You might also like