jdk source compilation on macos platform

Keywords: JDK macOS hotspot

1. Preface

_For java, a lot of work is done by jvm, such as memory allocation and recycling, other system-level calls. This actually blocks some things at the bottom of the operating system. It's convenient for javaer but also confusing (I'm not a pure javaer yet). Many of the detailed concepts are still not very clear, especially when it comes to underlying interactions. Especially when you are learning NIO (epoll&poll?, zero-copy?, userbuffer?, kernel buffer?).

In order to solve all kinds of internal doubts, or prepare to learn the underlying source of jdk. First, you need to download the JDK source code and compile it locally. Here you can clean it up (there are still many pits):

2. Local environment

  • macOS Monterey 12.0.1;
  • XCode needs to be installed Download Address ) Locally installed version 13.1;
  • brew install freetype & brew install ccache

3. pits of JDK9

  • First download the JDK9 source, download address: https://github.com/campolake/...;
  • Execute the following commands (Environment Check and Configuration) in the source root directory:
    bash ./configure --with-debug-level=slowdebug --with-jvm-variants=server --enable-ccache --with-freetype=/usr/local/Cellar/freetype/2.11.0 --disable-warnings-as-errors

    1. The freetype path changes itself according to your local environment;
    2. ccache Cache compiles code to speed up compilation and is unnecessary;
    3. disable-warnings-as-errors to avoid treating warning information as an error;
    4. with-debug-level is used to set the compilation level, optional values are release, fastdebug, slowde-bug, and the fewer optimization steps you take in the future, the more debugging information you have.

    After execution, the following prompts indicate that the next step is possible:

     A new configuration has been successfully created in
     using configure arguments '--with-debug-level=slowdebug --with-jvm-variants=server --enable-ccache --with-freetype=/usr/local/Cellar/freetype/2.11.0 --disable-warnings-as-errors'.
     Configuration summary:
     * Debug level:    slowdebug
     * HS debug level: debug
     * JDK variant:    normal
     * JVM variants:   server
     * OpenJDK target: OS: macosx, CPU architecture: x86, address length: 64
     * Version string: 9-internal+0-2021-12-03-105259.***.openjdk9 (9-internal)
     Tools summary:
     * Boot JDK:       java version "1.8.0_281" Java(TM) SE Runtime Environment (build 1.8.0_281-b09) Java HotSpot(TM) 64-Bit Server VM (build 25.281-b09, mixed mode)  (at /Library/Java/JavaVirtualMachines/jdk1.8.0_281.jdk/Contents/Home)
     * Toolchain:      clang (clang/LLVM from Xcode 13.1)
     * C Compiler:     Version 13.0.0 (at /usr/bin/clang)
     * C++ Compiler:   Version 13.0.0 (at /usr/bin/clang++)
     Build performance summary:
     * Cores to use:   16
     * Memory limit:   32768 MB
     * ccache status:  Active (4.5.1)
     The following warnings were produced. Repeated here for convenience:
     WARNING: Ignoring value of CCACHE from the environment. Use command line variables instead.
  • Execute make images and start compiling;
    Of course, things are not that simple. There were errors in the success of this step, as follows:

    /Users/yulewei/jdk9/hotspot/src/share/vm/memory/virtualspace.cpp:585:14: error: ordered comparison between pointer and zero ('char *' and 'int')
    if (base() > 0) {
       ~~~~~~ ^ ~
    /Users/yulewei/jdk9/hotspot/src/share/vm/opto/lcm.cpp:42:35: error: ordered comparison between pointer and zero ('address' (aka 'unsigned char *') and 'int')
    if (Universe::narrow_oop_base() > 0) { // Implies UseCompressedOops.
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~ 
    /Users/yulewei/jdk9/hotspot/src/share/vm/opto/loopPredicate.cpp:915:73: error: ordered comparison between pointer and zero ('const TypeInt *' and 'int')
       assert(rng->Opcode() == Op_LoadRange || _igvn.type(rng)->is_int() >= 0, "must be");
                                               ~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~

    This is a bug in JDK9. You need to modify the source file and recompile it. Refer to this article to solve it: https://segmentfault.com/a/11...

  • After recompiling the source file, a new error occurred:

    * For target hotspot_variant-server_libjvm_gtest_objs_gtestMain.o:
    clang: warning: include path for libstdc++ headers not found; pass   '-stdlib=libc++' on the command line to use the libc++ standard     library instead [-Wstdlibcxx-not-found]
    In file included from      /Users/***/CLionProjects/openjdk9/hotspot/test/native/gtestMain.cpp :33:
    In file included from  /Users/***/CLionProjects/openjdk9/hotspot/test/native/unittest.hpp: 29:
    /Users/***/CLionProjects/openjdk9/test/fmw/gtest/include/gtest/gtest.h:54:10: fatal error: 'limits' file not found
    #include <limits>
    1 error generated.
    * For target hotspot_variant-server_libjvm_gtest_objs_test_os.o:
    clang: warning: include path for libstdc++ headers not found; pass '-stdlib=libc++' on the command line to use the libc++ standard library instead [-Wstdlibcxx-not-found]
    In file included from /Users/***/CLionProjects/openjdk9/hotspot/test/native/runtime/test_os.cpp:25:
    In file included from /Users/***/CLionProjects/openjdk9/hotspot/src/share/vm/runtime/os.hpp:29:
    In file included from /Users/***/CLionProjects/openjdk9/hotspot/src/share/vm/runtime/extendedPC.hpp:28:
    /Users/***/CLionProjects/openjdk9/hotspot/src/share/vm/memory/allocation.hpp:38:10: fatal error: 'new' file not found
    #include <new>

    This problem is due to the newer version of XCode, the C language related header file could not be found. In fact, there are some in XCode, but the path is different from the old one. Add the following three parameters to the configure command:
    --with-extra-cflags=-stdlib=libc++ --with-extra-cxxflags=-stdlib=libc++ --with-extra-ldflags=-stdlib=libc++.
    This is the configure command:

    bash ./configure --with-debug-level=slowdebug --with-jvm-variants=server --enable-ccache --with-freetype=/usr/local/Cellar/freetype/2.11.0  --disable-warnings-as-errors --with-extra-cflags=-stdlib=libc++ --with-extra-cxxflags=-stdlib=libc++ --with-extra-ldflags=-stdlib=libc++
  • Execute make images again
    The following error occurred:

    # A fatal error has been detected by the Java Runtime Environment:
    #  SIGILL (0x4) at pc=0x0000000106321898, pid=39315, tid=8195
    # JRE version: OpenJDK Runtime Environment (9.0) (slowdebug build 9-internal+0-2021-12-03-133118.chensheng.openjdk9)
    # Java VM: OpenJDK 64-Bit Server VM (slowdebug 9-internal+0-2021-12-03-133118.chensheng.openjdk9, mixed mode, tiered, compressed oops, serial gc, bsd-amd64)
    # Problematic frame:
    # V  [libjvm.dylib+0xc1e898]  PerfData::~PerfData()+0x8
    # No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
    # If you would like to submit a bug report, please visit:
    #   http://bugreport.java.com/bugreport/crash.jsp

    After a lap of google, some said it was a hardware problem, but in the end it was really not done, we switched to JDK11.

4. Compile JDK11

  • First, you need to install jdk11 locally (jdk11 can be used to compile jdk11 without requiring a lower version of jdk), you can download the package directly and unzip it (you do not need to configure environment variables)
  • Download JDK11 source: https://github.com/openjdk/jd...
  • Execute configure

    bash ./configure --with-debug-level=slowdebug --with-boot-jdk=/Users/***/Applications/jdk11/jdk-11.0.12.jdk/Contents/Home --with-jvm-variants=server --enable-ccache --disable-warnings-as-errors --with-extra-cflags=-stdlib=libc++ --with-extra-cxxflags=-stdlib=libc++ --with-extra-ldflags=-stdlib=libc++

    --The value of the with-boot-jdk parameter is the absolute path to jdk11 after we unpacked it

  • Execute make images, once successful.

    It illustrates a problem that the new version (os&XCode) and the new version (jdk) are more appropriate

5. Debugging a hotspot virtual machine using clion

_clion uses cmake by default, but openjdk is compiled using make. If you don't want to write cMakeList yourself and want to reduce the probability of problems, refer to this article: https://segmentfault.com/a/11....
Not unexpectedly, it must be in place in one step.

_The environment has been finalized and we are starting to learn C again? {{{(><)}}}.

Posted by getmukesh on Mon, 06 Dec 2021 09:40:24 -0800