Categories: Java, Testing

Investigating a jtreg Failure

Download jtreg from the AdoptOpenJDK dependency pipeline (adoptopenjdk.net). For this investigation, I’ll be using my MacBook M1 running Monterey 12.1.

mkdir investigate
cd investigate
git clone https://github.com/openjdk/jdk11u

# Download jtreg 6
curl -Lo jtreg-6+1.tar.gz https://ci.adoptopenjdk.net/view/Dependencies/job/dependency_pipeline/lastSuccessfulBuild/artifact/jtreg/jtreg-6+1.tar.gz

tar xzfv jtreg-6+1.tar.gz

cd jdk11u

We switch the current directory to the root of jdk11u repo so that test paths are relative to the repo root. I will assume that we’re in the jdk11u repo root directory and are using the directory structure generated by the commands above. To see a detailed list of all the jtreg options, run this command:

../jtreg/bin/jtreg -help all

Now let us try to run a jtreg test, specifically AmazonCA.java:

../jtreg/bin/jtreg test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java

There are some failure messages but it looks like a test ran.

failed to get value for vm.hasJFR
java.lang.UnsatisfiedLinkError: 'boolean sun.hotspot.WhiteBox.isJFRIncludedInVmBuild()'
	at sun.hotspot.WhiteBox.isJFRIncludedInVmBuild(Native Method)
	at requires.VMProps.vmHasJFR(VMProps.java:343)
	at requires.VMProps$SafeMap.put(VMProps.java:72)
	at requires.VMProps.call(VMProps.java:107)
	at requires.VMProps.call(VMProps.java:60)
	at com.sun.javatest.regtest.agent.GetJDKProperties.run(GetJDKProperties.java:80)
	at com.sun.javatest.regtest.agent.GetJDKProperties.main(GetJDKProperties.java:54)
failed to get value for vm.aot.enabled
java.lang.UnsatisfiedLinkError: 'int sun.hotspot.WhiteBox.aotLibrariesCount()'
	at sun.hotspot.WhiteBox.aotLibrariesCount(Native Method)
	at requires.VMProps.vmAotEnabled(VMProps.java:408)
	at requires.VMProps$SafeMap.put(VMProps.java:72)
	at requires.VMProps.call(VMProps.java:112)
	at requires.VMProps.call(VMProps.java:60)
	at com.sun.javatest.regtest.agent.GetJDKProperties.run(GetJDKProperties.java:80)
	at com.sun.javatest.regtest.agent.GetJDKProperties.main(GetJDKProperties.java:54)
.
.
.
Test results: passed: 1
Report written to /Users/saint/repos/java/jdk11u/JTreport/html/report.html
Results written to /Users/saint/repos/java/jdk11u/JTwork

Are these failure messages concerning given that the test passed? Reviewing the test report suggests not. The report keywords mention bug 8233223, which must be Bug ID: JDK-8233223 Add Amazon Root CA certificates (java.com). From the look of things, the java.lang.UnsatisfiedLinkErrors can be safely ignored (for this test anyway). That said, let us dig into these errors to ensure we understand what is happening.

The immediate cause of these errors is the failure to get the values for the SafeMap in VMProps.java. This raises the question of which JDK is being used by jtreg? My MacBook has both JDK11 and JDK17. The default java version is:

java -version
openjdk version "17.0.1" 2021-10-19 LTS
OpenJDK Runtime Environment Microsoft-28056 (build 17.0.1+12-LTS)
OpenJDK 64-Bit Server VM Microsoft-28056 (build 17.0.1+12-LTS, mixed mode)

Let’s ensure jtreg is using JDK11 by setting JTREG_JAVA.

JTREG_JAVA=/Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home

$JTREG_JAVA/bin/java -version

openjdk version "11.0.14" 2022-01-18 LTS
OpenJDK Runtime Environment Microsoft-30257 (build 11.0.14+9-LTS)
OpenJDK 64-Bit Server VM Microsoft-30257 (build 11.0.14+9-LTS, mixed mode)

../jtreg/bin/jtreg test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java

We still see the same warnings though so let us explicitly use the -jdk option:

../jtreg/bin/jtreg -jdk:$JTREG_JAVA test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java

We now get an interesting error message indicating that the -jdk option was using the newer JDK17.

Exception while calling user-specified class: requires.VMProps
java.lang.UnsupportedClassVersionError: requires/VMProps has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 55.0
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	...
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:315)
	at com.sun.javatest.regtest.agent.GetJDKProperties.run(GetJDKProperties.java:78)
	at com.sun.javatest.regtest.agent.GetJDKProperties.main(GetJDKProperties.java:54)
failed to get JDK properties for /Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home/bin/java ; exit code 1
Error: failed to get JDK properties for /Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home/bin/java ; exit code 1

On my machine, I can remove these files as follows:

ls -l /Users/saint/repos/java/jdk11u/JTwork/extraPropDefns/classes/requires

rm -fr /Users/saint/repos/java/jdk11u/JTwork/extraPropDefns/classes/requires

Rerunning the test now results in a single (different) UnsatisfiedLinkError AND a test failure! However, we now have a properly set up environment since we control the JDK version tested by jtreg.

jdk11u % ../jtreg/bin/jtreg -jdk:$JTREG_JAVA test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java

failed to get value for vm.musl
java.lang.UnsatisfiedLinkError: 'java.lang.String sun.hotspot.WhiteBox.getLibcName()'
	at sun.hotspot.WhiteBox.getLibcName(Native Method)
	at requires.VMProps.isMusl(VMProps.java:514)
	at requires.VMProps$SafeMap.put(VMProps.java:72)
	at requires.VMProps.call(VMProps.java:122)
	at requires.VMProps.call(VMProps.java:60)
	at com.sun.javatest.regtest.agent.GetJDKProperties.run(GetJDKProperties.java:80)
	at com.sun.javatest.regtest.agent.GetJDKProperties.main(GetJDKProperties.java:54)
Test results: failed: 1
Report written to /Users/saint/repos/java/jdk11u/JTreport/html/report.html
Results written to /Users/saint/repos/java/jdk11u/JTwork
Error: Some tests failed or other problems occurred.

Now here’s an interesting question: why doesn’t this approach yield identical result to setting the -jdk flag to this same JTREG_JAVA path?

JTREG_JAVA=/Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home

../jtreg/bin/jtreg test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java

After doing some printf (or rather echo) debugging and observing an empty string for JTREG_JAVA, the culprit turns out to be the difference between a shell variable and an environment variable. See command line – What is the difference in usage between shell variables and environment variables? – Unix & Linux Stack Exchange. For the jtreg script to pull in this value of JTREG_JAVA, it needs to be an environment variable. It should therefore show up when this command is executed:

printenv | grep -i java

The proper way to execute this test then is:

JTREG_JAVA=/Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home

export JTREG_JAVA

../jtreg/bin/jtreg test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java

The outcome of the experiment so far though is that the AmazonCA test appears to fail when run with JDK11 and pass when run with JDK17 (of the respective versions). To convince ourselves that the infrastructure is fine, we can run this test with JDK11 (which is our focus) after exporting JTREG_JAVA.

../jtreg/bin/jtreg test/hotspot/jtreg/compiler/aot/cli/IncorrectAOTLibraryTest.java

This test passes, despite the single UnsatisfiedLinkError printed out.

failed to get value for vm.musl
java.lang.UnsatisfiedLinkError: 'java.lang.String sun.hotspot.WhiteBox.getLibcName()'
	at sun.hotspot.WhiteBox.getLibcName(Native Method)
	at requires.VMProps.isMusl(VMProps.java:514)
	at requires.VMProps$SafeMap.put(VMProps.java:72)
	at requires.VMProps.call(VMProps.java:122)
	at requires.VMProps.call(VMProps.java:60)
	at com.sun.javatest.regtest.agent.GetJDKProperties.run(GetJDKProperties.java:80)
	at com.sun.javatest.regtest.agent.GetJDKProperties.main(GetJDKProperties.java:54)
Test results: passed: 1
Report written to /Users/saint/repos/java/jdk11u/JTreport/html/report.html
Results written to /Users/saint/repos/java/jdk11u/JTwork

An Interesting Test

The above experimentation was inspired by AotInvokeDynamic2AotTest.java. The first time I tried to run this test, I used this command line.

../jtreg/bin/jtreg test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java

We first set of 5 UnsatisfiedLinkError failures in the previous experiment were displayed but no tests were executed.

...
Test results: no tests selected
Report written to /Users/saint/repos/java/jdk11u/JTreport/html/report.html

This was happening while jtreg was using JDK17 and one of the values that could not be get()ed vm.aot.enabled. Could that be why there were no selected tests? Ignoring that rabbit hole for now sine jdk11u is our focus. We can now run the test with JTREG_JAVA exported. The test is now run but fails with this message in JTreport/text/summary.txt:

compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java  Failed. Execution failed: `main' threw exception: java.lang.RuntimeException: Expected to get exit value of [0]

To see more details about the test failure, use the -verbose flag:

../jtreg/bin/jtreg -verbose:fail,error,summary test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java

Here is the a portion of the output of the test run. Notice the linker error in there!

ACTION: build -- Passed. All files up to date
REASON: Named class compiled on demand
TIME:   0.0 seconds
messages:
command: build compiler.aot.AotCompiler
reason: Named class compiled on demand
elapsed time (seconds): 0.0

ACTION: driver -- Failed. Execution failed: `main' threw exception: java.lang.RuntimeException: Expected to get exit value of [0]
REASON: User specified action: run driver compiler.aot.AotCompiler -libname AotInvokeDynamic2AotTest.so -class compiler.calls.common.InvokeDynamic -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:. 
TIME:   4.821 seconds
messages:
command: driver compiler.aot.AotCompiler -libname AotInvokeDynamic2AotTest.so -class compiler.calls.common.InvokeDynamic -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:.
reason: User specified action: run driver compiler.aot.AotCompiler -libname AotInvokeDynamic2AotTest.so -class compiler.calls.common.InvokeDynamic -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:. 
Mode: othervm
Additional options from @modules: --add-modules java.base --add-exports java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED --add-exports java.base/jdk.internal.misc=ALL-UNNAMED
elapsed time (seconds): 4.821
configuration:
Boot Layer
  add modules: java.base                                
  add exports: java.base/jdk.internal.misc              ALL-UNNAMED
               java.base/jdk.internal.org.objectweb.asm ALL-UNNAMED

STDOUT:
Command line: [/usr/bin/ld -v]
@(#)PROGRAM:ld  PROJECT:ld64-764
BUILD 11:22:50 Apr 28 2022
configured to support archs: armv6 armv7 armv7s arm64 arm64e arm64_32 i386 x86_64 x86_64h armv6m armv7k armv7m armv7em
LTO support using: LLVM version 13.1.6, (clang-1316.0.21.2.5) (static support for 28, runtime is 28)
TAPI support using: Apple TAPI version 13.1.6 (tapi-1316.0.7.3)

found working linker: /usr/bin/ld
Command line: [/Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home/bin/jaotc -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI -J-Xbootclasspath/a:. -J-classpath -J/Users/saint/repos/java/jdk11u/JTwork/classes/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.d:/Users/saint/repos/java/jdk11u/JTwork/classes/test/lib:/Users/saint/repos/java/jdk11u/JTwork/classes/testlibrary:/Users/saint/repos/java/jdk11u/JTwork/classes:/Users/saint/repos/java/jdk11u/test/hotspot/jtreg/compiler/aot/calls/fromAot --compile-with-assertions --info --output AotInvokeDynamic2AotTest.so --class-name compiler.calls.common.InvokeDynamic -J-ea -J-esa -J-Xmixed]
Compiling AotInvokeDynamic2AotTest.so...
1 classes found (22 ms)
9 methods total, 8 methods to compile (12 ms)
Compiling with 10 threads
.
8 methods compiled, 0 methods failed (2785 ms)
Parsing compiled code (7 ms)
Processing metadata (46 ms)
Preparing stubs binary (3 ms)
Preparing compiled binary (2 ms)
Creating binary: AotInvokeDynamic2AotTest.so.o (18 ms)
Creating shared library: AotInvokeDynamic2AotTest.so (30 ms)
Exception in thread "main" java.lang.InternalError: ld: dynamic main executables must link with libSystem.dylib for architecture x86_64
	at jdk.aot@11.0.14/jdk.tools.jaotc.Linker.link(Linker.java:142)
	at jdk.aot@11.0.14/jdk.tools.jaotc.Main.run(Main.java:262)
	at jdk.aot@11.0.14/jdk.tools.jaotc.Main.run(Main.java:133)
	at jdk.aot@11.0.14/jdk.tools.jaotc.Main.main(Main.java:89)

Why on earth is there an error about x86_64 on my M1? Here is the failing command line, listed separately for easy execution:

/Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home/bin/jaotc -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI -J-Xbootclasspath/a:. -J-classpath -J/Users/saint/repos/java/jdk11u/JTwork/classes/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.d:/Users/saint/repos/java/jdk11u/JTwork/classes/test/lib:/Users/saint/repos/java/jdk11u/JTwork/classes/testlibrary:/Users/saint/repos/java/jdk11u/JTwork/classes:/Users/saint/repos/java/jdk11u/test/hotspot/jtreg/compiler/aot/calls/fromAot --compile-with-assertions --info --output AotInvokeDynamic2AotTest.so --class-name compiler.calls.common.InvokeDynamic -J-ea -J-esa -J-Xmixed

Once this command completes (and fails), a file named AotInvokeDynamic2AotTest.so.o exists on disk. The format of the ld command can be deduced from Linker.java:101. The ld command can then be directly invoked to see the actual failure:

% ld -dylib -o AotInvokeDynamic2AotTest.so AotInvokeDynamic2AotTest.so.o
ld: dynamic main executables must link with libSystem.dylib for architecture x86_64

As per Clang -nostdlib option not working | Apple Developer Forums I tried adding the -lSystem option but that was not sufficient.

% ld -lSystem -dylib -o AotInvokeDynamic2AotTest.so AotInvokeDynamic2AotTest.so.o
ld: library not found for -lSystem

Exploring Mach-O, Part 1 | g.p. anders (gpanders.com) pointed out that the solution is to include the path to the lib folder as well!

ld -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/ -lSystem -dylib -o AotInvokeDynamic2AotTest.so AotInvokeDynamic2AotTest.so.o

The proper way to address this test failure then is to fix Linker.java to pass these additional flags to ld.


Categories: C, Java

Building Info-ZIP Source Code

I have been working on building the OpenJDK for the Windows ARM64 platform. The make images command has been failing in Cygwin with errors such as:

Creating java.se.jmod
zip I/O error: Device or resource busy
zip error: Could not create output file (/cygdrive/d/dev/repos/jdk/build/windows-aarch64-server-release/support/src.zip)
make[4]: *** [ZipSource.gmk:79: /cygdrive/d/dev/repos/jdk/build/windows-aarch64-server-release/support/src.zip] Error 1
make[4]: *** Deleting file '/cygdrive/d/dev/repos/jdk/build/windows-aarch64-server-release/support/src.zip'
make[3]: *** [ZipSource.gmk:93: zip] Error 2
make[2]: *** [make/Main.gmk:389: zip-source] Error 2
make[2]: *** Waiting for unfinished jobs....

ERROR: Build failed for target 'images' in configuration 'windows-aarch64-server-release' (exit code 2)

One of the troubleshooting approaches I tried was to build an instrumented zip executable to replace Cygwin’s zip.exe. I started by searching for the Cygwin zip package. Someone was kind enough to have a link to the Cygwin zip package’s official page which in turn linked to the Cygwin zip packaging repository. This repo’s tree view shows a single file with source URIs for zip and that’s how I learned that this zip utility was Info-ZIP. The Zip 3.0 page has a link to Info-ZIP’s SourceForge site, from which the zip sources can be downloaded. I used curl in the Windows Terminal as follows:

curl -Lo zip30.tar.gz https://sourceforge.net/projects/infozip/files/Zip%203.x%20%28latest%29/3.0/zip30.tar.gz/download
tar xvf zip30.tar.gz
cd ./zip30
git init; git add *; git commit -m "Commit original Info-ZIP sources"

Now that we have the sources, let’s see how to build them. The scenario I’m working on is Windows specific so we need Visual Studio 2019 with the Desktop Development with C++ workload installed. I’ll be building a 32-bit zip executable. Launch the x86 Native Tools Command Prompt for VS 2019 and change to the zip30 source directory to start building. Some digging around reveals a makefile with build instructions (that seem one directory off). Here’s the command to build a 32-bit executable from the sources (note that building fails due to various errors that need to be addressed):

nmake -f win32\makefile.w32

Carriage Return (CR) Name Collisions

The first error is this rather cryptic mess of syntax errors:

Microsoft (R) Program Maintenance Utility Version 14.29.30133.0
Copyright (C) Microsoft Corporation.  All rights reserved.

        cl -nologo -c -W3 -O2 -DWIN32 -DASM_CRC -ML  zip.c
cl : Command line warning D9002 : ignoring unknown option '-ML'
zip.c
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18822): error C2143: syntax error: missing ':' before 'constant'
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18822): error C2143: syntax error: missing ';' before ':'
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18822): error C2059: syntax error: ':'
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18823): error C2143: syntax error: missing '{' before ':'
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18823): error C2059: syntax error: ':'
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18824): error C2059: syntax error: '}'
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18825): error C2059: syntax error: '}'
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18826): error C2059: syntax error: '}'
zip.c(5746): warning C4267: '=': conversion from 'size_t' to 'ush', possible loss of data
zip.c(5838): warning C4267: '=': conversion from 'size_t' to 'ush', possible loss of data
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133\bin\HostX86\x86\cl.EXE"' : return code '0x2'
Stop.

Some head banging (and not looking at the precompiler output from cl -c -W3 -O2 -DWIN32 -DASM_CRC /P zip.c carefully) leads to c – Compiler errors in WINNT.H after retargeting solution to latest SDK (10.0.18362) – Stack Overflow where the solution is rather simple: do not use the name CR to define the carriage return since it maps to a bitfield in one of the structs in winnt.h. See Rename CR identifier to avoid collisions with ARM64 structs in winnt.h by swesonga · Pull Request #2 · swesonga/Info-ZIP (github.com)

Outdated Linker Flags

The next error is a complaint about the /OPT:NOWIN98 flag.


        link -nologo user32.lib advapi32.lib /OPT:NOWIN98 /INCREMENTAL:NO /PDB:zip.pdb  /RELEASE zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj  crc32.obj crci386c.obj globals.obj deflate.obj trees.obj match32.obj win32.obj win32zip.obj nt.obj win32i64.obj zip.res
LINK : fatal error LNK1117: syntax error in option 'OPT:NOWIN98'
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133\bin\HostX86\x86\link.EXE"' : return code '0x45d'
Stop.

Turns out this option was removed in Visual Studio 2010 as per the Microsoft C/C++ change history since the linker no longer supports optimizing for Windows 98. This is clearly a safe flag to remove from the linker flags in win32\makefile.w32.

Update the Branding

  1. Change the VERSION string from “3.0” to “3.0-ioHardenedZIP”
  2. Update the REVDATE from “July 5th 2008” to the current date (“December 18th 2021” in my case)
  3. Update the about text to indicate that it is a custom build.

Testing the Zip Build

The sources should now build successfully in the x86 Native Tools Command Prompt for VS 2019. The OpenJDK build uses the -qru flags for creating zip files so we can easily test the zip executable by creating a zip of the Info-ZIP help and license text.

zip -h > help.txt
zip -h2 > help2.txt
zip -L > license.txt
zip -qru ./files.zip -i *.txt

We need to verify whether the zip was correctly created. Saving this for another day.

Building on Linux/macOS

[Update 2021-12-22] To build Info-ZIP on macOS, the way the memset function is detected needs to be fixed. Info-ZIP for either Linux or macOS can then be built using this command:

make -f unix/Makefile generic

Categories: DevOps, Java

Windows OpenJDK Development Environment Setup

I documented how to set up an OpenJDK build environment for macOS and for Ubuntu Linux. Here is how to do the same for a Windows x86-64 environment on a Windows x86-64 machine. To create a JDK build for a Windows ARM64 environment, see the last section of this post.

  1. Install Visual Studio Code.
  2. Install Git and set Visual Studio Code as Git’s default editor.
  3. Install Visual Studio 2019. Ensure the Desktop Development with C++ workload is selected so that the C++ compiler is available.
The Visual Studio Desktop development with C++ workload
  1. Install a boot JDK. I used winget, the Windows package manager, to do this as outlined in the OpenJDK Windows installation instructions.
winget search Microsoft.OpenJDK
winget install Microsoft.OpenJDK.17
Microsoft Build of OpenJDK with Hotspot 17.0.1+12 (x64) 
Please watt while Windows configures Microsoft Build of OpenJDK with 
Hotspot 170 1+12(x64) 
Time remaining 7 seconds
  1. Install Cygwin using the command below.
setup-x86_64.exe -q -P autoconf -P make -P unzip -P zip
  1. Launch Cygwin, clone the OpenJDK repo then run bash configure. This should output an error if there are any missing dependencies. Once that completes successfully, make images will build the OpenJDK code.
mkdir ~/repos
cd ~/repos
git clone https://github.com/openjdk/jdk
cd ~/repos/jdk
bash configure
make images

To try out the local JDK build, run java.exe in the build folder, e.g.

cd ~/repos/jdk/build/windows-x86_64-server-slowdebug
cd jdk/bin
./java.exe -version

Troubleshooting

Keep in mind that make images can fail due to Cygwin-specific issues. The only workaround may be to downgrade Cygwin to a version known to work well, as I had to do when I ran into segfaults when running make.

Windows ARM64 JDK

To create a JDK build for a Windows ARM64 machine (as of this posting), you still need to set up the Windows x86-64 environment as described above with the additional changes below.

  1. Launch the Visual Studio Installer then install the “MSVC v142 – VS 2019 C++ ARM64 build tools (Latest)” item.
  2. Run bash configure with the additional –openjdk-target argument as outlined at https://github.com/microsoft/openjdk-aarch64
bash configure --openjdk-target=aarch64-unknown-cygwin

Running the ARM64 JDK on x86-64?

I was curious to see what happens if you try to run the ARM64 Java build in Cygwin on x86-64:

User@Machine /cygdrive/c/dev/repos/jdk/build/windows-aarch64-server-release/jdk/bin
$ ./java -version
-bash: ./java: cannot execute binary file: Exec format error

In the Windows command line we get this message in the terminal and the subsequent dialog box:

C:\dev\repos\jdk\build\windows-aarch64-server-release\jdk\bin>.\java.exe
This version of C:\dev\repos\jdk\build\windows-aarch64-server-release\jdk\bin\java.exe is not compatible with the version of Windows you're running. Check your computer's system information and then contact the software publisher.
Machine Type Mismatch

Launching it from Windows Explorer fails with this error:

Platform mismatch launching ARM64 Java on Windows x86-64

Categories: DevOps, Java

Set up macOS for OpenJDK Development

Last week I bought a new MacBook Pro with the Apple M1 Chip and 16GB of RAM. These are the steps I used to set it up for building the OpenJDK codebase.

General macOS Configuration

  1. Set the OS appearance (theme). I tend to prefer dark theme.
  2. Set your Mac’s name (it bothers me when the terminal has some random host name). You might need to restart your terminal for this change to take effect.

Install Development Tools

Should any of the commands below fail, see the troubleshooting section at the end for possible workarounds.

  1. Install homebrew by running the recommended command (and see the troubleshooting section if there are any git errors):
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  1. Clone the OpenJDK repo:
mkdir ~/repos
cd ~/repos
git clone https://github.com/openjdk/jdk
  1. Install Xcode from the App Store. Xcode 13.1 is the most recent as of this post.
  2. Download and install the Xcode command line tools.
  3. Select the Xcode command line tools: launch Xcode then go to Preferences > Locations. Select Xcode 13.1 in the Command Line Tools dropdown as shown below.
Selecting the Command Line Tools in Xcode
  1. Install autoconf: brew install autoconf
  2. Install Visual Studio Code (optional)

Installing the Boot JDK

This was surprisingly straightforward. The instructions on how to install the Microsoft Build of OpenJDK on macOS comprise a single homebrew command:

brew install --cask microsoft-openjdk

Installing the Microsoft OpenJDK on macOS

Building the OpenJDK

Running bash configure in the JDK folder should display any missing dependencies. Any errors from bash configure will need to be resolved before running make images.

cd ~/repos/jdk
bash configure
make images

To browse through the contents of the build folder in finder:

open ~/repos/jdk/build/

To try out your new build, switch to the bin folder and check the Java version:

cd ~/repos/jdk/build/macosx-aarch64-server-release/jdk/bin
./java -version

Here is the output I get:

saint@Saints-MBP-2021 bin % ./java -version
openjdk version "18-internal" 2022-03-22
OpenJDK Runtime Environment (build 18-internal+0-adhoc.saint.jdk)
OpenJDK 64-Bit Server VM (build 18-internal+0-adhoc.saint.jdk, mixed mode)
saint@Saints-MBP-2021 bin % 

Troubleshooting

Homebrew Installation Failure

Installing homebrew appeared to be successful (last message output below) but there was a git error in the output!

==> Downloading and installing Homebrew..
remote: Enumerating objects: 345, done.
remote: Counting objects: 100% (297/297), done.
remote: Compressing objects: 100% (107/107), done.
remote: Total 345 (delta 227), reused 238 (delta 184), pack-reused 48
Receiving objects: 100% (345/345), 171.73 KiB | 971.00 KiB/s, done.
Resolving deltas: 100% (227/227),
completed with 54 local objects.
From https://github.com/Homebrew/brew
* [new branch]
dependabot/bundler/Librarv/Homebrew/sorbet-0.5.9396
-> origin/dependabot/bundler/Librarv/Homebrew/sorbet-0.5.9396
778de69b0..be908f679 master -> origin/master
* [new tag] 3.3.6 -> 3.3.6
HEAD is now at be908f679 Merge pull request #12502 from carlocab/bug-template
error: Not a valid ref: refs/remotes/origin/master
fatal: ambiguous argument
'refs/remotes/origin/master': unknown revision or path not in the working tree.
Use
"_-' to separate paths from revisions, like this:
'git <command> [<revision>...] - I<files...11
fatal: Could not resolve HEAD to a revision
Warning: /opt/homebrew/bin is not in your PATH.
Instructions on how to configure vour shell for Homebrew
can be found in the 'Next steps' section below.
==> Installation successful!

Here is the relevant error, which I was able to copy/paste (with some typos) from the PNG!!!

error: Not a valid ref: refs/remotes/origin/master
fatal: ambiguous argument
'refs/remotes/origin/master': unknown revision or path not in the working tree.

I thought I could keep chugging along merrily but other steps will fail if this is not addressed. Thankfully, https://stackoverflow.com/questions/65605282/trying-to-install-hugo-via-homebrew-could-not-resolve-head-to-a-revision already addressed how to fix this. I had to look up the -C flag in the git docs (it executes the command in the context of the specified directory).

git -C $(brew --repository homebrew/core) checkout master
Fixing the homebrew/core git repo

Autoconf Installation Failures

No available formula with the name “autoconf”

I ran into errors of the form No available formula with the name "autoconf" when attempting to install autoconf. However, this happen with the unresolved brew installation git issue described above. Once that was resolved, https://stackoverflow.com/questions/11552171/cant-install-software-using-brew-on-my-mac helpfully pointed out that autoconf is part of the command line tools package (hence step 4 in the instructions above).

[saint@Saints-MBP-2021 jk % brew install autoconf
fatal: Could not resolve HEAD to a revision
Running 'brew update --preinstall'
==> Homebrew is run entirelv by unpaid volunteers. Please consider donating:
https://github.com/Homebrew/brew#donations
==› Auto-updated Homebrew!
Updated 1 tap (homebrew/cask).
==> Updated Casks
dated 1 cask.
Warning: No available formula with the name
"autoconf"
==› Searching for similarlv named formulae.
Error: No similarly named formulae found.
==> Searching for a previously deleted formula (in the last month).
Error: No previously deleted formula found.
==> Searching taps on GitHub.
Error: No formulae found in taps.

No Such File or Directory @ dir_chdir

Setting up a build environment on my Intel MacBook Pro led to errors like this:

==> Installing autoconf dependency: m4
Error: No such file or directory @ dir_chdir - /usr/local/Cellar

The workaround from https://programmerah.com/brew-install-node-error-no-such-file-or-directory-dir_chdir-bottle-installation-failed-5943/ is to simply reinstall brew.

Missing Xcodebuild tool

One of my bash configure runs failed with this error:

checking for sdk name..
configure: error: No xcodebuild tool and no system framework headers found, use --with-sysroot or --with-sdk-name to provide a path to a valid SDK
/Users/saint/repos/idk/build/.configure-support/generated-configure.sh: line 84: 5: Bad file descriptor
configure exiting with result code 1

This was because the command line tools had not been selected in Xcode as show in step 6. This resolution came from https://stackoverflow.com/questions/17980759/xcode-select-active-developer-directory-error.