banner
NEWS LETTER

How to compile JDK in M1 MacBook——在M1上编译JDK

Scroll down

最近开始看《深入理解Java虚拟机》,出来混果然还是要还的,就从最基础的债开始还起吧。第一部分主要是编译JDK,由于个人是M1芯片,导致编译过程中出现诸多问题,网上又少有相关报错,导致花费了不少时间

System Environment

Workspace Specs
OS
Chip
Xcode
Xcode Comand Line Tools If you have installed homebrew before, then homebrew will automatically install it for you, and if not, please refer to this article.
Homebrew

Get JDK source code

  1. First, we need to download the source code of openJDK12 from the openJDK’s official website

  2. If the JDK’s version that we want to compile is N , then we need to prepare another JDK whose version has to be N-1 at least. That’s because part of JDK is written by Java, so we need another available JDK in compile time when we compile it, and such another JDK is officially called ‘Bootstrap JDK‘. So we need to install openJDK 11 with instruction brew install cask adoptopenjdk11 had we install homebrew before.

  3. The directory structure is as follows:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    openjdk
    ├── ADDITIONAL_LICENSE_INFO
    ├── ASSEMBLY_EXCEPTION
    ├── CONTRIBUTING.md
    ├── LICENSE
    ├── Makefile
    ├── README.md
    ├── bin
    ├── build
    ├── configure
    ├── doc
    ├── make
    ├── src
    └── test

Configure

  1. Execute bash configure in the root directory of the JDK you just get, you will get the error message like this If all goes well:

    1
    configure: The tested number of bits in the target (64) differs from the number of bits expected to be found in the target (32) configure: error: Cannot continue.

    The reason is clearly clarifed in this question:

    Apple Silicon chips M1, M2 are all 64-bits architectures. Do not compiler for 32-bit

    So we have to get openJDK 17, which is a relatively new version and available for M1. We also need to prepare a new Bootstrap JDK which should be Java 16. Use the same instruction brew install cask adoptopenjdk16

  2. Rerun bash configure, then you will get a new error like this:

    1
    X 'sprintf' is deprecated: This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use snprintf(3) instead.

    As you can see from the message, sprintf is considered insecurity, but we can miss it by adding a parameter --disable warnings as errors, so rerun bash configure --disable warnings as errors

  3. If you are fortunate enough, you will see success message:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    Configuration summary:

    * Name: macosx-aarch64-server-release
    * Debug level: release
    * HS debug level: product
    * JVM variants: server
    * JVM features: server: 'cds compiler1 compiler2 dtrace epsilongc g1gc jfr jni-check jvmci jvmti management nmt parallelgc serialgc services shenandoahgc vm-structs zgc'
    * OpenJDK target: OS: macosx, CPU architecture: aarch64, address length: 64
    * Version string: 17-internal+0-adhoc.effy.openjdkbackup (17-internal)

    Tools summary:

    * Boot JDK: openjdk version "16.0.2" 2021-07-20 OpenJDK Runtime Environment Zulu16.32+15-CA (build 16.0.2+7) OpenJDK 64-Bit Server VM Zulu16.32+15-CA (build 16.0.2+7, mixed mode) (at /Users/effy/Library/Java/JavaVirtualMachines/azul-16.0.2/Contents/Home)
    * Toolchain: clang (clang/LLVM from Xcode 14.3)
    * C Compiler: Version 14.0.3 (at /usr/bin/clang)
    * C++ Compiler: Version 14.0.3 (at /usr/bin/clang++)

    Build performance summary:

    * Cores to use: 8
    * Memory limit: 16384 MB

Make images

  1. Excute make images, then you’ll get an error like this:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    === Output from failing command(s) repeated here ===
    * For target support_interim-jmods_support__create_java.base.jmod_exec:
    #
    # A fatal error has been detected by the Java Runtime Environment:
    #
    # Internal Error (assembler_aarch64.hpp:248), pid=56946, tid=9987
    # guarantee(val < (1ULL << nbits)) failed: Field too big for insn
    #
    # JRE version: (17.0.3) (build )
    # Java VM: OpenJDK 64-Bit Server VM (17.0.3+0-jvmci-22.1-b05, mixed mode, emulated-client, sharing, tiered, compressed oops, compressed class ptrs, serial gc, bsd-aarch64)
    # No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
    #
    # An error report file with more information is saved as:
    # /opt/labs-openjdk-17/make/hs_err_pid56946.log
    #
    #
    * For target support_interim-jmods_support__create_java.logging.jmod_exec:
    #
    # A fatal error has been detected by the Java Runtime Environment:
    #
    # Internal Error (assembler_aarch64.hpp:248), pid=56929, tid=10243
    # guarantee(val < (1ULL << nbits)) failed: Field too big for insn
    #
    # JRE version: (17.0.3) (build )
    # Java VM: OpenJDK 64-Bit Server VM (17.0.3+0-jvmci-22.1-b05, mixed mode, emulated-client, sharing, tiered, compressed oops, compressed class ptrs, serial gc, bsd-aarch64)
    # No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
    #
    # An error report file with more information is saved as:
    # /opt/labs-openjdk-17/make/hs_err_pid56929.log
    #
    #

    * All command lines available in /opt/labs-openjdk-17/build/labsjdk/make-support/failure-logs.
    === End of repeated output ===

    No indication of failed target found.
    Hint: Try searching the build log for '] Error'.
    Hint: See doc/building.html#troubleshooting for assistance.

    gmake[3]: Leaving directory '/opt/labs-openjdk-17'
    make[2]: *** [/opt/labs-openjdk-17/make/Init.gmk:315: main] Error 2
    make[2]: Leaving directory '/opt/labs-openjdk-17'
    make[1]: *** [/opt/labs-openjdk-17/make/Init.gmk:186: graal-builder-image] Error 2
    make[1]: Leaving directory '/opt/labs-openjdk-17'
    make: *** [labs17.makefile:27: /opt/labs-17/bin/java] Error 2
  2. You need to do like this issue does, and add some codes in src/hotspot/cpu/aarch64/immediate_aarch64.cpp.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    uint64_t replicate(uint64_t bits, int nbits, int count)
    {
    + assert(count > 0, "must be");
    + assert(nbits > 0, "must be");
    + assert(count * nbits <= 64, "must be");
    +
    + // Special case nbits == 64 since the shift below with that nbits value
    + // would result in undefined behavior.
    + if (nbits == 64) {
    + return bits;
    + }

    uint64_t result = 0;
    // nbits may be 64 in which case we want mask to be -1
    uint64_t mask = ones(nbits);
    for (int i = 0; i < count ; i++) {
    result <<= nbits;
  3. Rerun make images, you will get the last error:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    Compiling 56 files for java.sql.rowset
    Compiling 82 files for jdk.jlink
    Compiling 95 files for jdk.jshell
    error: invalid integral value '16-DMAC_OS_X_VERSION_MIN_REQUIRED=10120' in '-mstack-alignment=16-DMAC_OS_X_VERSION_MIN_REQUIRED=10120'
    make[3]: *** [/Users/jdk/build/macosx-x86_64-server-fastdebug/hotspot/variant-server/libjvm/objs/bsd_x86_64.o] Error 1
    make[3]: *** Waiting for unfinished jobs....
    Compiling 229 files for jdk.javadoc
    make[2]: *** [hotspot-server-libs] Error 2
    make[2]: *** Waiting for unfinished jobs....
    Compiling 2736 files for java.desktop

    ERROR: Build failed for target 'images' in configuration 'macosx-x86_64-server-fastdebug' (exit code 2)
    Stopping sjavac server

    make[1]: *** [main] Error 2
    === Output from failing command(s) repeated here ===
    make: *** [images] Error 2
    * For target hotspot_variant-server_libjvm_objs_bsd_x86_64.o:
    error: invalid integral value '16-DMAC_OS_X_VERSION_MIN_REQUIRED=10120' in '-mstack-alignment=16-DMAC_OS_X_VERSION_MIN_REQUIRED=10120'

    * All command lines available in /Users/jdk/build/macosx-x86_64-server-fastdebug/make-support/failure-logs.
    === End of repeated output ===
  4. Fortunatelly, you just need to do like this issue, add two ‘spaces’ in make/autoconf/flags-other.m4, it’s quite weird right?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
      # Fix linker warning.
    # Code taken from make/autoconf/flags-cflags.m4 and adapted.
    - JVM_BASIC_ASFLAGS+="-DMAC_OS_X_VERSION_MIN_REQUIRED=$MACOSX_VERSION_MIN_NODOTS \
    + JVM_BASIC_ASFLAGS+=" -DMAC_OS_X_VERSION_MIN_REQUIRED=$MACOSX_VERSION_MIN_NODOTS \
    -mmacosx-version-min=$MACOSX_VERSION_MIN"
    if test -n "$MACOSX_VERSION_MAX"; then
    - JVM_BASIC_ASFLAGS+="$OS_CFLAGS \
    + JVM_BASIC_ASFLAGS+=" $OS_CFLAGS \
    -DMAC_OS_X_VERSION_MAX_ALLOWED=$MACOSX_VERSION_MAX_NODOTS"
    fi
    fi

Reference

1: how-to-compile-openjdk-11-on-an-m1-macbook

2: hotspot arm64 bug exposed by latest clang

3: Build failure with Xcode 13.0 after JDK-8264848

4: 深入理解Java虚拟机(第三版),周志明