一、前言
对于java来说,很多工作都被jvm包揽了,比如内存分配和回收、其他系统级别调用。这其实就把操作系统底层的一些东西给屏蔽了,对于javaer来说,方便的同时也带来一些困惑(我还不是一个纯javaer),很多细节性概念始终不是很通透,特别是当涉及底层交互的时候。特别是学NIO那块东西的时候(epoll&poll?、zero-copy?、userbuffer?、kernel buffer?
)。
为了解决内心的种种疑惑,还是准备学习jdk的底层源码。首先需要下载jdk源码,并在本地编译,下面开整(还是有很多坑):
二、本地环境
- macOS Monterey 12.0.1;
- 需要安装XCode【下载地址】,本地安装版本13.1;
- brew install freetype & brew install ccache
三、JDK9的坑
- 首先下载JDK9源码,下载地址:https://github.com/campolake/...;
在源码根目录执行如下命令(环境检查和配置):
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
freetype
(字体引擎)路径根据本地环境自己更改;ccache
缓存编译代码,加速编译,可以不用;disable-warnings-as-errors
避免将warning信息当成error;with-debug-level
用来设置编译的级别,可选值为release、fastdebug、slowde-bug,越往后进行的优化措施就越少,带的调试信息就越多。
执行完出现如下提示就表示可以下一步了:
A new configuration has been successfully created in /Users/***/CLionProjects/openjdk9/build/macosx-x86_64-normal-server-slowdebug 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.
执行
make images
,开始编译;
事情当然没有那么简单,在这一步成功出现了报错,如下:/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"); ~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~
这个是JDK9的bug,需要修改源码文件然后重新编译,参考这篇文章解决:https://segmentfault.com/a/11...
改完源码文件重新编译,出现新的报错:
* 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
^~~~~ 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 ^~~~~ 这个问题是由于XCode版本比较新导致,找不到C语言相关的头文件。其实XCode中是有的,只是路径和老的不一样了,在
configure
命令中添加如下3个参数就行:--with-extra-cflags=-stdlib=libc++ --with-extra-cxxflags=-stdlib=libc++ --with-extra-ldflags=-stdlib=libc++
。
configure命令就是这样的了: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++
再一次执行
make images
出现如下报错:# # 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 #
google了一圈,有的说是硬件问题,最后实在没搞定,就换成JDK11了。
四、编译JDK11
- 首先需要先在本地安装jdk11(jdk11可以用来编译jdk11,不需要低一个版本的jdk),可以直接下载压缩包然后解压(不需要配置环境变量)
- 下载JDK11源码:https://github.com/openjdk/jd...
执行
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++
--with-boot-jdk
参数的值就是我们解压后jdk11的绝对路径执行
make images
,一次成功。说明了一个问题,新版本(
os
&XCode
)和新版本(jdk
)才更适配
五、使用clion调试hotspot虚拟机
clion默认是用cmake
,但是编译openjdk是用make
,如果不想自己写cMakeList
且想减少出问题概率,参考这篇文章:https://segmentfault.com/a/11...。
不出意外,一定可以一步到位。
环境终于搞定了,又要开始学C语言了? {{{(>_<)}}}。