To analyze the JVM’s source code, direct reading is one way, but in some confusing scenarios, you must combine debugging, viewing the execution path, and the specific values of the parameters to make sense. So let’s first compile the JVM source code, and be able to use GDB for debugging.

Compile environment

This article USES the JDK version: OpenJDK7, branch b147 download page: https://download.java.net/openjdk/jdk7 download address: http://download.java.net/openjdk/jdk7/promoted/b147/openjdk-7-fcs-src-b147-27jun2011.zipMD5: c284c89a104f64a95afde3a96138ef0f

Other environmental instructions:

  • CentOS 7.4 64
  • GCC Version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
  • The GNU Make 3.82

Install dependencies

yum -y install gcc gcc-c++ make yum -y install alsa-lib-devel yum -y install cups-devel yum -y install libX* yum -y install gcc gcc-c++ yum -y install libstdc++-static wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo  yum -y install antCopy the code

To compile the JVM, you need to use an earlier version of the JDK, for example, you need to install OracleJDK6. https://www.oracle.com/java/technologies/javase-java-archive-javase6-downloads.htmlhttp://gcdncs.101.com/v0.1/static/tes T_mzb/jdK-6u38-linux-x64-rpm.bin Download: JDK-6u38-linux-x64-rpm.bin

$ sh jdk-6u38-linux-x64-rpm.bin
$ sudo rpm -ivh jdk-6u38-linux-amd64.rpmCopy the code

Writing compilation scripts

Unzip its:

unzip openjdk-7-fcs-src-b147-27_jun_2011.zipCopy the code

Add a build.sh script to the openJDK directory:

#! /bin/bash export LANG=C # Set the following two items as your BootstrapJDK installation directory export ALT_BOOTDIR=/usr/ Java /jdk1.6.0_38 export ALT_JDK_IMPORT_PATH=/usr/java/jdk1.6.0_38 export ALLOW_DOWNLOADS=true Export USE_PRECOMPILED_HEADER=true # I only selected LANGTOOLS, HOTSPOT and JDK export BUILD_LANGTOOLS=true export BUILD_JAXP=false export BUILD_JAXWS=false export BUILD_CORBA=false export BUILD_HOSTPOT=true export BUILD_JDK=true # Build to build export SKIP_DEBUG_BUILD=false export SKIP_FASTDEBUG_BUILD=true export DEBUG_NAME=debug # Avoid build BUILD_DEPLOY=false for Javaws and browser Java plug-ins etc BUILD_INSTALL=false # Export ENABLE_FULL_DEBUG_SYMBOLS=1 # If set to 1,libjvm.debuginfo is compressed to libjvm.diz and cannot be debugged. Export ZIP_DEBUGINFO_FILES=0 # Number of threads to compile export HOTSPOT_BUILD_JOBS=3 # Set the directory for storing the compiled results #export ALT_OUTPUTDIR=/root/ JVM /output unset CLASSPATH unset JAVA_HOME make sanity DEBUG_BINARIES=true make 2>&1Copy the code

Then run sh build.sh to compile. If you encounter problems during compilation, refer to the compilation problem Resolution section below.

Run the HotSpot

After a successful compilation, the output is stored in the openJDK /build directory by default. The HotSpot compiler output in its/build/Linux – amd64 – debug/HotSpot/outputdir/linux_amd64_compiler2 / JVMG directory.

Perform tests using the commands provided by HotSpot:

CD build/Linux - amd64 - debug/hotspot/outputdir/linux_amd64_compiler2 / JVMG # test_gamma is a hotspot to provide a test procedure, /test_gamma # GDB debugging with hotspot script./hotspot - GDB HelloWorldCopy the code

./hotspot is a script that does some simple things by looking at the code, mainly setting environment variables:

JAVA_HOME = / usr/Java/jdk1.6.0 _38 LD_LIBRARY_PATH = / root/JVM/its/build/Linux - amd64 - debug/hotspot/outputdir/linux_amd64_compiler2 / JVMG: / usr/Java/jdk1.6. 0_38/jre/lib/amd64Copy the code

Then generate the GDB parameter script and run the GDB command:

gdb -x /tmp/hsl.26037Copy the code

/ TMP /hsl.26037 is the GDB parameter generated by the script, we can see what is set:

cd /root/jvm/openjdk/build/linux-amd64-debug/hotspot/outputdir/linux_amd64_compiler2/jvmg
handle SIGUSR1 nostop noprint
handle SIGUSR2 nostop noprint
set args HelloWorld 
file /root/jvm/openjdk/build/linux-amd64-debug/hotspot/outputdir/linux_amd64_compiler2/jvmg/gamma
directory /root/jvm/openjdk/build/linux-amd64-debug/hotspot/outputdir/linux_amd64_compiler2/jvmg
# Get us to a point where we can set breakpoints in libjvm.so
break InitializeJVM
run
# Stop in InitializeJVM
delete 1
# We can now set breakpoints wherever we likeCopy the code

You can see that the source directory is set and a default breakpoint is set. After analyzing the Hotspot script, we can start Hotspot and GDB in the most primitive way possible to implement more complex debugging requirements, such as remote debugging.

Direct execution:

JAVA_HOME = / usr/Java/jdk1.6.0 _38 LD_LIBRARY_PATH = "/ root/JVM/its/build/Linux - amd64 - debug/hotspot/outputdir/linux_amd64_compiler2 / JVMG: / usr/Java/jdk1.6 .0_38/jre/lib/amd64" ./gamma HelloWorldCopy the code

GDB debugging:

JAVA_HOME = / usr/Java/jdk1.6.0 _38 LD_LIBRARY_PATH = "/ root/JVM/its/build/Linux - amd64 - debug/hotspot/outputdir/linux_amd64_compiler2 / JVMG: / usr/Java/jdk1.6 .0_38/jre/lib/amd64" gdb ./gamma HelloWorldCopy the code

GDB remote debugging:

JAVA_HOME = / usr/Java/jdk1.6.0 _38 LD_LIBRARY_PATH = "/ root/JVM/its/build/Linux - amd64 - debug/hotspot/outputdir/linux_amd64_compiler2 / JVMG: / usr/Java/jdk1.6 .0_38/jre/lib/amd64" gdbserver :8011 ./gamma HelloWorldCopy the code

Hotspot code debugging tips

GDB usage and skills will not be mentioned here, I am also encountered problems now check information, here are a few commonly used and HotSpot related debugging skills.

How to print the string corresponding to HotSpot’s internal Symbol object Symbol?

Symbol is a very common class, all symbols refer to the corresponding string, such as the class name, method name, method signature, etc.

p *name._body@name._lengthCopy the code

How to print the class name for KlassHandle?

p Klass::cast(current_klass.obj())->external_name()Copy the code

Add breakpoints for loading specific classes

break ClassFileParser::parseClassFile if strncmp(class_name._body, "XXX", 3) == 0
break SystemDictionary::load_instance_class if strncmp(class_name._body, "XXX", 3) == 0Copy the code

Problems encountered

Setting the BootstrapJDK to JDK8 initially will fail. Change to JDK6Copy the code

# error echo "*** This OS is not supported:" 'uname -a'; exit 1; # solve sudo vim its/hotspot/make/Linux/Makefile comment out the following three lines of 238 # ifeq ($(DISABLE_HOTSPOT_OS_VERSION_CHECK)$(EMPTY_IF_NOT_SUPPORTED),) 239 # $(QUIETLY) >&2 echo "*** This OS is not supported:" `uname -a`; exit 1; 240 #endifCopy the code

# error:"__LEAF"redefined [-werror] # Error :"__LEAF"redefined [-werror] This and hotspot/SRC/share/vm/runtime/interfaceSupport HPP conflict with the macro definition in a header file, under 428 lines we increase a # undef __LEAF is as follows:  428 // LEAF routines do not lock, GC or throw exceptions #ifdef __LEAF #undef __LEAF #define __LEAF(result_type, header) \ TRACE_CALL(result_type, header) \ debug_only(NoHandleMark __hm;) \ /* begin of body */ #endifCopy the code

# Error Error: / its/hotspot/SRC/share/vm/oops/constantPoolOop CPP: 272-39: Error: Converting 'false' to pointer type 'methodOop' [-werror =conversion-null] # Hotspot/SRC/share/vm/oops/constantPoolOop, CPP will line 272 return false to return NULLCopy the code

# error/usr/its/hotspot/SRC/share/vm/opto/loopnode CPP: 896:49: error: Converting 'false' to pointer type 'Node * [- Werror = conversion - null] # solve vi hotspot/SRC/share/vm/opto/loopnode CPP will 896 rows Return false Changed to return NULLCopy the code

Using Java Runtime at: /usr/lib/jvms /java-1.6.0/jre./gamma: relocation error: / usr/lib/JVM/Java 1.6.0 - its - 1.6.0.41. X86_64 / jre/lib/amd64 libjava. So: symbol JVM_FindClassFromCaller, Version sunWprivate_1.1 not defined in file libjvm.so with link time reference Please install the Oracle JDK 1.6 in advance. # ALT_BOOTDIR < < OpenJDK 1.6.0 > < < OpenJDK 1.6.0 > < < < OpenJDK 1.6.0 > > / usr/lib/JVM/Java 1.6.0 - its - 1.6.0.41. X86_64 / jre/lib/amd64 libjava. So: symbol JVM_FindClassFromCaller, Version sunWPrivate_1.1 not defined in file libjvm.so with link time reference Download portal may require login to Oracle. Jkp-6u38-linux-x64-rpm. If the last portal fails, please continue! If this transfer also fails (T_T), then send, drag to the bottom of the page, go to the Java Archive bar, and click the DOWNLOAD button on the right to send yourself. Download bin to baidu ~ ~ ~ # $sh JDK -6u38-linux-x64-rpm JDK 6 u38 - Linux - amd64. RPM # OK so far has completed Oracle JDK installation # # Oracle JDK installation directory search JDK installation name $RPM - qa | grep ^ JDK - 1.6.0 $RPM -ql jdK-1.6.0_38-fcs.x86_64 # RPM -ql JDK-1.6.0_38-FCs.x86_64 # RPM -ql JDK-1.6.0_38-FCs.x86_64 /usr/java/jdk1.6.0_38 # Oracle JDK HOME... The directory found above will be used laterCopy the code

GCC: error: Unrecognized Command line option '-mimpure-text' Vi JDK/make/common/Shared/Compiler - GCC. GMK in 70 lines of remove the command "- mimpure - text" in the code:Copy the code

Error: time is more than 10 years from present: 1136059200000 Error: time is more than 10 years from present: 1136059200000 vi jdk/src/share/classes/java/util/CurrencyData.properties # line: 108 377 439 529 555Copy the code

Error:.. /.. /.. /src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java:661: error: No suitable constructor found for SslRMIServerSocketFactory (SSLContext, String [], String [], Boolean) solution: Vi. / JDK/SRC/share/classes/sun/management/jmxremote/ConnectorBootstrap Java comment out 662 line parametersCopy the code

data

  • In-depth Understanding of the Java Virtual Machine
  • Openjdk7 compile and debug | YDDMAX https://yddmax.github.io/2017/06/11/openjdk7%E4%B9%8B%E7%BC%96%E8%AF%91%E5%92%8Cdebug/
  • Centos7 compile openjdk7 FAQ – clover 灬 OSCHINA – https://my.oschina.net/zhangdq/blog/2250314
  • How to build and package OpenJDK 7 on Linux · hgomez/obuildfactory Wiki https://github.com/hgomez/obuildfactory/wiki/How-to-build-and-package-OpenJDK-7-on-Linux
  • Compile ubuntu16.04 JDK7 – Jane books at https://www.jianshu.com/p/32dc1a850e23
  • Building OpenJDK7 with CentOS7 – Rtfsc8 http://blog.rtfsc8.top/2018/07/07/building-openjdk7-with-centos7/
  • Compiling OpenJDK8 source code on CentOS and debugging HotSpot VM source code on Eclipse – Tjiyu’s blog – CSDN blog

In this paper, the independent blog: the JVM source analysis – the JVM source code to compile and debug | wood of Chinese fir blog