1. 程式人生 > >編譯你的第一個Java虛擬機--Centos 7 編譯openJdk1.7源碼

編譯你的第一個Java虛擬機--Centos 7 編譯openJdk1.7源碼

... 沒有 相關 rmdir cnblogs int 了解 grep rac

一、前言

最近在看《深入java虛擬機》,看完後,打算自己實際編譯一個jvm出來看看,實踐一下。

書上提到了Oracle JDK和OpenJdk的關系,Oracle Jdk7 和OpenJdk 7共用了相當多的代碼,所以還是很有學習的必要的:

技術分享圖片

技術分享圖片

二、環境

我這裏的編譯的操作系統是CentOS Linux release 7.4.1708 (Core) (通過 cat /etc/centos-release查看)。

編譯環境相當重要,因為編譯openjdk的過程中,網上的文章裏,大家遇到的各個問題都不一樣,就是因為操作系統不一致。

我主要參考了某位園友的博客:https://www.cnblogs.com/gotodsp/p/8975387.html

該博客裏有他用到的工具的百度網盤鏈接。大家可自行下載。我是下載了之後,通過centos中安裝的lrzsz命令來上傳的。

命令為rz(上傳),sz(下載)。

沒安裝的話,執行 yum install lrzsz

下面是另一個參考的博客:

http://blog.51cto.com/wangyahui/1612838

我這裏引用了不少原博客的內容,但是中間還是有很多問題。我這裏會補充說明。

2.1 卸載原jdk

rpm -qa | grep java

yum -y remove XXXX --XXXX是第一條命令查出來的jdk信息

2.2 編譯相關的工具

yum -y install gcc gcc-c++ alsa-lib alsa-lib-devel libXrender libXrender-devel libXi-devel libXt-devel libXtst-devel cups cups-devel

2.3 FreeType

註意:我這邊,會把所有工具,最後都解壓到/usr/local目錄下。先上一張我最後成功了的圖:

技術分享圖片

tar -zxvf freetype-2.4.0.tar.gz -C /usr/local

cd /usr/local/freetype-2.4.0

./configure && make && make install   # 編譯安裝

##註意:如果安裝中出現以下錯誤

rmdir /usr/local/include/freetype2/freetype/internal
rmdir: failed to remove `/usr/local/include/freetype2/freetype/internal‘: No such file or directory

make: [install] Error 1 (ignored)
/usr/bin/install -c -m 644 ./builds/unix/ft2unix.h \
/usr/local/include/ft2build.h
/usr/bin/install -c -m 644 ./builds/unix/ftconfig.h \
/usr/local/include/freetype2/freetype/config/ftconfig.h

執行以下命令處理:

mkdir -p /usr/local/include/freetype2/freetype/internal

重新安裝

./configure && make && make install

2.4 Apache Ant

tar -zxvf apache-ant-1.9.7-bin.tar.gz -C /usr/local # 解壓

ln -s /usr/local/apache-ant-1.9.7/bin/ant /usr/bin/ant  # 軟鏈接到bin

2.5 BootstrapJDK

上傳到你的虛擬機上後,

chmod +x jdk-6u45-linux-x64.bin

./jdk-6u45-linux-x64.bin   # 解壓

mv jdk1.6.0_45 /usr/local/  # 移動目錄

然後 vim /etc/profile,配置:

#java environment
export JAVA_HOME=/usr/local/jdk1.6.0_45
export CLASSPATH=.:${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar
export PATH=$PATH:${JAVA_HOME}/bin

然後執行 source /etc/profile.

再執行java -version試試,看看是不是生效。

2.6 OpenJdk

unzip openjdk-7-fcs-src-b147-27_jun_2011.zip   # 解壓

原文章中說得有點亂,不管怎樣,做成下面我這種目錄效果就行:

技術分享圖片

三、準備環境變量

vim /etc/profile #在末尾加以下內容。註意其中的目錄的路徑,另外,先不要忙著執行,先把這一節看完:

export ANT_HOME=/usr/local/apache-ant-1.9.7

export ALT_FREETYPE_HEADERS_PATH=/usr/local/include/freetype2
export ALT_FREETYPE_LIB_PATH=/usr/local/lib
export ALT_DROPS_DIR=/usr/local/src/openjdk/drop
export ALT_BOOTDIR=/usr/local/jdk1.6.0_45
export ALT_JDK_IMPORT_PATH=/usr/local/jdk1.6.0_45
export ALT_OUTPUTDIR=/usr/local/openjdk_output
export LANG=C
export HOTSPOT_BUILD_JOBS=8
export ALT_PARALLEL_COMPILE_JOBS=8
export SKIP_COMPARE_IMAGES=true
export USE_PRECOMPILED_HEADER=true
export ALLOW_DOWNLOADS=true
export SKIP_DEBUG_BUILD=false
export SKIP_FASTDEBUG_BUILD=true
export DEBUG_NAME=debug
export BUILD_LANGTOOLS=true
export BUILD_HOTSPOT=true
export BUILD_JDK=true
export BUILD_DEPLOY=false
export BUILD_INSTALL=false
unset JAVA_HOME
unset CLASSPATH
unset LD_LIBRARY_PATH

這裏依次解釋下各個選項:

  • ANT_HOME # 編譯工具ant的路徑
  • ALT_FREETYPE_HEADERS_PATH # freetype2頭文件安裝目錄,一般無需替換
  • ALT_FREETYPE_LIB_PATH # 這個也無需修改
  • ALT_DROPS_DIR #這個目錄很重要,下圖來自參考的那位園友的博客裏的:

技術分享圖片

  • ALT_BOOTDIR #啟動jdk的路徑
  • ALT_JDK_IMPORT_PATH #看文章裏是配成一致的,暫時還不知道配成不一致的結果
  • ALT_OUTPUTDIR #最終編譯輸出的位置,來個直觀圖展示下

  技術分享圖片

  • LANG ##語言選項,這個必須設置,否則編譯好後會出現一個HashTable的NPE錯
  • HOTSPOT_BUILD_JOBS #並行編譯的線程數,設置為和CPU內核數量一致即可
  • ALT_PARALLEL_COMPILE_JOBS #並行編譯的線程數,設置為和CPU內核數量一致即可
  • SKIP_COMPARE_IMAGES #比較本次build出來的映像與先前版本的差異。這對我們來說沒有意義,必須設置為true,否則sanity檢查會報缺少先前版本JDK的映像的錯誤提示。
  • USE_PRECOMPILED_HEADER #使用預編譯頭文件,不加這個編譯會更慢一些
  • ALLOW_DOWNLOADS #允許自行下載依賴
  • SKIP_DEBUG_BUILD #要編譯的版本
  • SKIP_FASTDEBUG_BUILD 要編譯的版本
  • BUILD_LANGTOOLS # 是否編譯語言工具
  • BUILD_HOTSPOT #編譯虛擬機
  • BUILD_JDK 編譯jdk
  • BUILD_DEPLOY #把它設置為false可以避開javaws和瀏覽器Java插件之類的部分的build
  • BUILD_INSTALL #把它設置為false就不會build出安裝包。因為安裝包裏有些奇怪的依賴,但即便不build出它也已經能得到完整的JDK映像,所以還是別build它好了

  • unset JAVA_HOME unset CLASSPATH unset LD_LIBRARY_PATH #這三個環境變量必須去掉,不然會有很詭異的事情發生(我沒有具體查過這些"詭異的#事情",Makefile腳本檢查到有這2個變量就會提示警告)

設置完了後,保存,刷新一下。 source /etc/profile

四、檢查

在/usr/local/src/openjdk下運行 make sanity。

如果最後一行顯示:

Sanity check passed.

則表示檢查通過。

五、編譯jvm

在同上目錄下,執行 make DISABLE_HOTSPOT_OS_VERSION_CHECK=ok

之所以加DISABLE_HOTSPOT_OS_VERSION_CHECK=ok,是因為遇到了下面的異常:

ERROR:××× recipe for target ‘check_os_version’ failed ×××

為了跳過版本校驗,所以加了上述參數。

參考了:https://blog.csdn.net/desiyonan/article/details/80801830

好了,接下來靜靜等待,我最後那一次成功的編譯,花了大概20-30分鐘,成功了,會有如下顯示(突然發現前面tree了一把,刷屏了,只能網上去找個圖了。。。):

技術分享圖片

(別人家怎麽那麽快,10分鐘。。。)

我這邊還是貼一個我這邊編譯好的虛擬機的version顯示吧:

技術分享圖片

如果你沒那麽幸運,發生了各種error,導致make中斷的話,不要走開。參考下面一節。

六、遇到的問題

ps:如果看到提示某個文件報錯,又不知道在哪,大家直接用find / -name abc.txt查找吧。

1、Error: time is more than 10 years from present: 1136059200000

通過修改CurrencyData.properties文件, 把10年之前的時間修改為10年之內即可
Index: /usr/openjdk/jdk/src/share/classes/java/util/CurrencyData.properties

註意,該文件內有5,6處要修改的地方。不要漏了,漏了又是10+分鐘。。

2、 /usr/bin/ld: cannot find -lstdc++

Linking vm...
/usr/bin/ld: cannot find -lstdc++
collect2: error: ld returned 1 exit status
/usr/bin/chcon: cannot access ‘libjvm.so‘: No such file or directory
ERROR: Cannot chcon libjvm.so
/usr/bin/objcopy --only-keep-debug libjvm.so libjvm.debuginfo
/usr/bin/objcopy: ‘libjvm.so‘: No such file
make[4]: *** [libjvm.so] Error 1
make[4]: Leaving directory `/usr/src/openjdk/hotspot/build/hotspot_debug/linux_amd64_compiler2/debug‘
make[3]: *** [the_vm] Error 2
make[3]: Leaving directory `/usr/src/openjdk/hotspot/build/hotspot_debug/linux_amd64_compiler2/debug‘
make[2]: *** [debug] Error 2
make[2]: Leaving directory `/usr/src/openjdk/hotspot/build/hotspot_debug‘
make[1]: *** [generic_build2] Error 2
make[1]: Leaving directory `/usr/src/openjdk/hotspot/make‘
make: *** [debug] Error 2


解決:

yum search libc++
yum install libstdc++-static

3、不識別‘-mimpure-text‘參數

報錯:gcc: error: unrecognized command line option ‘-mimpure-text‘

make[5]: *** [/openjdk/build/linux-amd64/../linux-amd64-debug/lib/amd64/libverify.so] Error 1

解決:

就在 openjdk源碼中的,/make/common/shared/Compiler-gcc.gmk 中去掉 -mimpure-text 命令

4、constantPoolOop.cpp

Error:/openjdk/hotspot/src/share/vm/oops/constantPoolOop.cpp:272:39: error: converting ‘false‘ to pointer type ‘methodOop‘ [-Werror=conversion-null]

將return false 改為return NULL

5、__LEAF 頭文件重復定義問題

/openjdk/hotspot/src/share/vm/runtime/interfaceSupport.hpp:430:0: error: "__LEAF" redefined [-Werror]
#define __LEAF(result_type, header)

/usr/include/x86_64-linux-gnu/sys/cdefs.h:42:0: note: this is the location of the previous definition
# define __LEAF , __leaf__

在interfaceSupport.hpp代碼的最前面增加:(後面的\也是需要的,宏定義中的換行符)

#ifdef __LEAF
#undef __LEAF

#define __LEAF(result_type, header) \
TRACE_CALL(result_type, header) \
debug_only(NoHandleMark __hm;) \
/* begin of body */
#endif

6、/hotspot/src/share/vm/opto/loopnode.cpp:896:49: error: converting ‘fals‘ to pointer type ‘Node*‘ [-Werror=conversion-null]

解決:修改openjdk/hotspot/src/share/vm/opto/loopnode.cpp: 第896行 return false改為return (Node*)false; 或者 return NULL;

7、無法下載包問題 Redirection detected from https to http. Protocol switch unsafe, not allowed

解決:其實前面已經提到了,網盤裏提供了jdk6-jaf-b20.zip、jdk6-jaxp-b20.zip、jdk6-jaxws-b20.zip三個文件即為了解決該問題。將這三個文件復制到openjdk/drop目錄下。

同時要配置ALT_DROPS_DIR指向該目錄。

七、總結

今天搞這個+寫博客,差不多大半天了。。。

一千個人編譯jdk,就會有一千個錯誤。。。

關鍵是等得又久,錯了又得重來。。。不過再怎麽說,還是很有成就感的。

看了書,就得實踐,畢竟老祖宗說的:紙上得來終覺淺,絕知此事要躬行。

編譯你的第一個Java虛擬機--Centos 7 編譯openJdk1.7源碼