一、JDK 選型:拒絕 “通用版”,適配架構(gòu)是關(guān)鍵
坑點(diǎn)表現(xiàn):安裝 OpenJDK 通用版本后,出現(xiàn) “JVM 創(chuàng)建失敗”(錯(cuò)誤碼 1003)或 JNI 接口不兼容,在飛騰 ARM64、龍芯 MIPS64 架構(gòu)服務(wù)器上尤為頻發(fā)。
根因:麒麟系統(tǒng)深度綁定國產(chǎn) CPU 架構(gòu),通用 JDK 未適配底層指令集,導(dǎo)致類庫缺失或二進(jìn)制接口不兼容。
避坑方案:
- 按 CPU 架構(gòu)精準(zhǔn)選型(見下表):
CPU 架構(gòu) | 推薦 JDK 版本 | 驗(yàn)證命令 |
飛騰 ARM64 | 麒麟 JDK11 for ARM64 | java -version | grep aarch64 |
龍芯 MIPS64 | 麒麟 JDK11 for MIPS64 | java -version | grep mips64 |
海光 X86_64 | 麒麟 JDK11 for x86_64 | java -version | grep x86_64 |
- 卸載系統(tǒng)預(yù)裝的 “兼容版 JDK”:sudo apt purge openjdk-8-jre
- 用官方腳本安裝:
wget https://kylinos.cn/down/jdk11-arm64.deb
sudo dpkg -i jdk11-arm64.deb
二、環(huán)境變量:避免 “臨時(shí)生效”,持久化配置有講究
坑點(diǎn)表現(xiàn):執(zhí)行java -version顯示正常,但服務(wù)啟動(dòng)時(shí)提示 “未找到 Java 環(huán)境”(錯(cuò)誤碼 101),重啟服務(wù)器后配置丟失。
根因:僅在當(dāng)前終端執(zhí)行export命令,未寫入系統(tǒng)配置文件;或混淆bash與zsh的配置路徑。
避坑方案:
- 定位 JDK 真實(shí)路徑:ls /usr/lib/jvm/(通常為java-11-kylin-arm64)
- 寫入全局配置(所有用戶生效):
sudo tee /etc/profile.d/java.sh << 'EOF'
export JAVA_HOME=/usr/lib/jvm/java-11-kylin-arm64
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib
EOF
- 強(qiáng)制生效并驗(yàn)證:
source /etc/profile
echo $JAVA_HOME # 輸出上述路徑即為成功
三、依賴庫適配:警惕 “native 庫陷阱”,跨架構(gòu)需重編
坑點(diǎn)表現(xiàn):項(xiàng)目啟動(dòng)時(shí)報(bào) “依賴未加載”(錯(cuò)誤碼 1004),如 Netty 的epoll庫、Hadoop 的本地存儲(chǔ)庫加載失敗。
根因:第三方庫的*.so文件為 X86 架構(gòu)編譯,與國產(chǎn) ARM/MIPS 架構(gòu)不兼容。
避坑方案:
- 優(yōu)先選用 “國產(chǎn)化適配庫”:
- 中間件:星環(huán) TDH(適配麒麟的大數(shù)據(jù)平臺(tái))、東方通 TongWeb(替代 Tomcat)
- 數(shù)據(jù)庫驅(qū)動(dòng):達(dá)夢 JDBC 驅(qū)動(dòng)(dm.jdbc.driver.DmDriver)
- 自行編譯 native 庫(以 Netty 為例):
# 安裝交叉編譯工具
sudo apt install gcc-aarch64-linux-gnu
# 克隆源碼并指定架構(gòu)編譯
git clone https://github.com/netty/netty.git
cd netty
mvn clean package -DskipTests -Pnative -Dnative.targetArch=aarch64
- 用ldd命令排查缺失庫:ldd target/libnetty-transport-native-epoll.so
四、JVM 調(diào)優(yōu):摒棄 “默認(rèn)參數(shù)”,適配麒麟 GC 策略
坑點(diǎn)表現(xiàn):服務(wù)運(yùn)行中頻繁 OOM,或 GC 耗時(shí)過長,麒麟 JDK 默認(rèn)啟用 Parallel Scavenge GC 導(dǎo)致低延遲場景不達(dá)標(biāo)。
根因:國產(chǎn) JVM 的 GC 實(shí)現(xiàn)與 Oracle JDK 存在差異,默認(rèn)參數(shù)未針對麒麟系統(tǒng)優(yōu)化。
避坑方案:
- 核心參數(shù)配置(ARM64 架構(gòu)服務(wù)器,16GB 內(nèi)存為例):
java -jar app.jar \
-XX:+UnlockExperimentalVMOptions \ # 解鎖麒麟JDK實(shí)驗(yàn)性參數(shù)
-XX:+UseG1GC \ # 切換至低延遲G1 GC
-Xms8g -Xmx8g \ # 堆內(nèi)存設(shè)為物理內(nèi)存50%
-XX:MaxGCPauseMillis=200 \ # 控制GC停頓時(shí)間
-XX:+PrintGCDetails -Xloggc:gc.log # 輸出GC日志便于分析
- 禁用 “大頁內(nèi)存”(麒麟系統(tǒng)默認(rèn)關(guān)閉,開啟易導(dǎo)致內(nèi)存分配失敗):
echo "vm.nr_hugepages=0" | sudo tee -a /etc/sysctl.conf
- 用麒麟自帶工具監(jiān)控:kylin-jvm-monitor -pid [進(jìn)程ID]
五、安全權(quán)限:破解 “訪問受限”,SELINUX 與端口配置
坑點(diǎn)表現(xiàn):服務(wù)無法綁定 80/443 端口,或讀寫/tmp目錄時(shí)報(bào) “權(quán)限拒絕”,排查發(fā)現(xiàn) SELinux 阻止操作。
根因:麒麟系統(tǒng)默認(rèn)啟用強(qiáng)化安全策略,對特權(quán)端口、系統(tǒng)目錄訪問限制嚴(yán)格。
避坑方案:
- 非 root 用戶綁定低端口(無需關(guān)閉 SELinux):
# 分配端口綁定能力
sudo setcap CAP_NET_BIND_SERVICE=+eip $JAVA_HOME/bin/java
# 驗(yàn)證:普通用戶可綁定80端口
java -jar app.jar --server.port=80
- 配置 SELINUX 策略(生產(chǎn)環(huán)境不建議關(guān)閉):
# 創(chuàng)建自定義策略文件
sudo tee app_selinux.te << 'EOF'
module app_selinux 1.0;
require { type unconfined_t; type tmp_t; class file write; }
allow unconfined_t tmp_t:file write;
EOF
# 編譯并加載策略
checkmodule -M -m -o app_selinux.mod app_selinux.te
semodule_package -o app_selinux.pp -m app_selinux.mod
sudo semodule -i app_selinux.pp
- 調(diào)整文件描述符限制(解決高并發(fā)連接問題):
sudo tee /etc/security/limits.d/java.conf << 'EOF'
* soft nofile 65535
* hard nofile 65535
EOF