While reading Understanding the JVM – Advanced Features and Best Practices, Second Edition (in Chinese) recently, there is a guide in chapter one to build JVM from source. It is based on OpenJDK7, which only works when using a Java6/Java7 VM as build bootstrap. Java8 bootstrap has more strict code checks and will finally fail the build. So, I just switched to a more recent OpenJDK8 code. The file name is openjdk-8u40-src-b25-10_feb_2015.zip
.
The code provides a better build experience, and compiles on my Linux box almost out of box. But remember, do not use a gcc compiler >= gcc-6. It defaults to C++14 and breaks the build. On macOS, the build scripts seem only support gcc. Actually, a clang compiler is required to build the objc code.
1. So the first step after downloading and unzipping the code, modify the configure script:
1 2 |
# cd openjdk # vi common/autoconf/generated-configure.sh |
Comment out the lines(2 appearances):
1 |
as_fn_error $? "GCC compiler is required. Try setting --with-tools-dir." "$LINENO" 5 |
2. Now install freetype and run configure:
1 2 |
# brew install freetype # bash ./configure --prefix=/Users/gonwan/openjdk-runtime --with-debug-level=slowdebug --with-freetype-include=/usr/local/Cellar/freetype/2.8.1/include/freetype2 --with-freetype-lib=/usr/local/Cellar/freetype/2.8.1/lib --with-milestone=special --with-update-version=u01 --with-build-number=b01 |
A slowdebug
build disables optimization and helps a lot when debugging. The summary output looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Configuration summary: * Debug level: slowdebug * JDK variant: normal * JVM variants: server * OpenJDK target: OS: macosx, CPU architecture: x86, address length: 64 Tools summary: * Boot JDK: java version "1.8.0_152" Java(TM) SE Runtime Environment (build 1.8.0_152-b16) Java HotSpot(TM) 64-Bit Server VM (build 25.152-b16, mixed mode) (at /Library/Java/JavaVirtualMachines/jdk1.8.0_152.jdk/Contents/Home) * C Compiler: version (at /usr/bin/gcc) * C++ Compiler: version (at /usr/bin/g++) Build performance summary: * Cores to use: 2 * Memory limit: 16384 MB * ccache status: not installed (consider installing) |
3. Apply the following patch to fix build errors. Partially picked from an official OpenJDK10 changeset:
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 46 47 48 |
diff -ru openjdk.old/hotspot/src/share/vm/opto/lcm.cpp openjdk/hotspot/src/share/vm/opto/lcm.cpp --- openjdk.old/hotspot/src/share/vm/opto/lcm.cpp 2017-12-01 13:24:42.000000000 +0800 +++ openjdk/hotspot/src/share/vm/opto/lcm.cpp 2017-12-01 13:25:35.000000000 +0800 @@ -57,7 +57,7 @@ // Check whether val is not-null-decoded compressed oop, // i.e. will grab into the base of the heap if it represents NULL. static bool accesses_heap_base_zone(Node *val) { - if (Universe::narrow_oop_base() > 0) { // Implies UseCompressedOops. + if (Universe::narrow_oop_base() != 0) { // Implies UseCompressedOops. if (val && val->is_Mach()) { if (val->as_Mach()->ideal_Opcode() == Op_DecodeN) { // This assumes all Decodes with TypePtr::NotNull are matched to nodes that diff -ru openjdk.old/hotspot/src/share/vm/opto/loopPredicate.cpp openjdk/hotspot/src/share/vm/opto/loopPredicate.cpp --- openjdk.old/hotspot/src/share/vm/opto/loopPredicate.cpp 2017-12-01 13:24:42.000000000 +0800 +++ openjdk/hotspot/src/share/vm/opto/loopPredicate.cpp 2017-12-01 13:26:08.000000000 +0800 @@ -772,7 +772,7 @@ Node* idx = cmp->in(1); assert(!invar.is_invariant(idx), "index is variant"); Node* rng = cmp->in(2); - assert(rng->Opcode() == Op_LoadRange || _igvn.type(rng)->is_int() >= 0, "must be"); + assert(rng->Opcode() == Op_LoadRange || _igvn.type(rng)->is_int()->_lo >= 0, "must be"); assert(invar.is_invariant(rng), "range must be invariant"); int scale = 1; Node* offset = zero; diff -ru openjdk.old/hotspot/src/share/vm/runtime/virtualspace.cpp openjdk/hotspot/src/share/vm/runtime/virtualspace.cpp --- openjdk.old/hotspot/src/share/vm/runtime/virtualspace.cpp 2017-12-01 13:24:42.000000000 +0800 +++ openjdk/hotspot/src/share/vm/runtime/virtualspace.cpp 2017-12-01 13:26:41.000000000 +0800 @@ -332,7 +332,7 @@ (UseCompressedOops && (Universe::narrow_oop_base() != NULL) && Universe::narrow_oop_use_implicit_null_checks()) ? lcm(os::vm_page_size(), alignment) : 0) { - if (base() > 0) { + if (base() != 0) { MemTracker::record_virtual_memory_type((address)base(), mtJavaHeap); } diff -ru openjdk.old/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m openjdk/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m --- openjdk.old/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m 2017-12-01 13:24:33.000000000 +0800 +++ openjdk/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m 2017-12-01 13:28:37.000000000 +0800 @@ -36,7 +36,7 @@ static jobject appkitThreadGroup = NULL; static BOOL awtEmbedded = NO; -inline void attachCurrentThread(void** env) { +static inline void attachCurrentThread(void** env) { if ([NSThread isMainThread]) { JavaVMAttachArgs args; args.version = JNI_VERSION_1_4; |
1 |
# patch -p1 < ../openjdk8.patch |
4. Start the build:
1 2 3 4 |
# export USE_CLANG=true # export COMPILER_WARNINGS_FATAL=false # export LFLAGS='-Xlinker -lstdc++' # make |
Lots of warnings, but the build should finish successfully:
1 2 3 4 5 6 7 8 9 10 11 |
----- Build times ------- Start 2017-12-01 13:33:20 End 2017-12-01 13:41:30 00:00:28 corba 00:02:39 hotspot 00:00:15 jaxp 00:00:22 jaxws 00:03:53 jdk 00:00:32 langtools 00:08:10 TOTAL ------------------------- |
5. Debugging with lldb:
The output binary lie in openjdk/build/macosx-x86_64-normal-server-slowdebug/jdk
. The output of java -version
:
1 2 3 |
openjdk version "1.8.0_u01-special-debug" OpenJDK Runtime Environment (build 1.8.0_u01-special-debug-b01) OpenJDK 64-Bit Server VM (build 25.40-b25-debug, mixed mode) |
Never used lldb
before, seems to be compatible with gdb
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# lldb ./java (lldb) target create "./java" Current executable set to './java' (x86_64). (lldb) b main Breakpoint 1: 21 locations. (lldb) run -version Process 67998 launched: './java' (x86_64) Process 67998 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #0: 0x000000010000d5b2 java`main(argc=2, argv=0x00007ffeefbff9c8) at main.c:97 94 { 95 int margc; 96 char** margv; -> 97 const jboolean const_javaw = JNI_FALSE; 98 #endif /* JAVAW */ 99 #ifdef _WIN32 100 { Target 0: (java) stopped. (lldb) p argv[1] (char *) $0 = 0x00007ffeefbffb27 "-version" (lldb) |