JDK8 升級常見問題
JDK8 發布很久了,它提供了許多吸引人的新特性,能夠提高編程效率。
如果是新的項目,使用 JDK8 當然是最好的選擇。但是,對於一些老的項目,升級到 JDK8 則存在一些兼容性問題,是否升級需要酌情考慮。
近期,我在工作中遇到一個任務,將部門所有項目的 JDK 版本升級到 1.8 (老版本大多是 1.6)。在這個過程中,遇到一些問題點,並結合在網上看到的坑,在這里總結一下。
Intellij 中的 JDK 環境設置
Settings
點擊 File > Settings > Java Compiler
Project bytecode version 選擇 1.8
點擊 File > Settings > Build Tools > Maven > Importing
選擇 JDK for importer 為 1.8
Projcet Settings
Project SDK 選擇 1.8
Application
如果 web 應用的啟動方式為 Application ,需要修改 JRE
點擊 Run/Debug Configurations > Configuration
選擇 JRE 為 1.8
Linux 環境修改
修改環境變量
修改 /etc/profile
中的 JAVA_HOME,設置 為 jdk8 所在路徑。
修改后,執行 source /etc/profile
生效。
檢查環境變量是否添加成功測試:
echo $JAVA_HOME
編譯、發布腳本中如果有 export JAVA_HOME
,需要注意,需要使用 jdk8 的路徑。
修改 maven
settings.xml 中 profile 的激活條件如果是 jdk,需要修改一下 jdk 版本
<activation>
<jdk>1.8</jdk> <!-- 修改為 1.8 -->
</activation>
修改 server
修改 server 中的 javac 版本,以 resin 為例:
修改 resin 配置文件中的 javac 參數。
<javac compiler="internal" args="-source 1.8"/>
sun.* 包缺失問題
JDK8 不再提供 sun.*
包供開發者使用,因為這些接口不是公共接口,不能保證在所有 Java 兼容的平台上工作。
使用了這些 API 的程序如果要升級到 JDK 1.8 需要尋求替代方案。
雖然,也可以自己導入包含 sun.*
接口 jar 包到 classpath 目錄,但這不是一個好的做法。
需要詳細了解為什么不要使用 sun.*
,可以參考官方文檔:Why Developers Should Not Write Programs That Call 'sun' Packages
默認安全策略修改
升級后估計有些小伙伴在使用不安全算法時可能會發生錯誤,so,支持不安全算法還是有必要的
找到\$JAVA_HOME 下 jre/lib/security/java.security
,將禁用的算法設置為空:jdk.certpath.disabledAlgorithms=
。
JVM 參數調整
在 jdk8 中,PermSize 相關的參數已經不被使用:
-XX:MaxPermSize=size
Sets the maximum permanent generation space size (in bytes). This option was deprecated in JDK 8, and superseded by the -XX:MaxMetaspaceSize option.
-XX:PermSize=size
Sets the space (in bytes) allocated to the permanent generation that triggers a garbage collection if it is exceeded. This option was deprecated un JDK 8, and superseded by the -XX:MetaspaceSize option.
JDK8 中再也沒有 PermGen
了。其中的某些部分,如被 intern 的字符串,在 JDK7 中已經移到了普通堆里。其余結構在 JDK8 中會被移到稱作“Metaspace”的本機內存區中,該區域在默認情況下會自動生長,也會被垃圾回收。它有兩個標記:MetaspaceSize 和 MaxMetaspaceSize。
-XX:MetaspaceSize=size
Sets the size of the allocated class metadata space that will trigger a garbage collection the first time it is exceeded. This threshold for a garbage collection is increased or decreased depending on the amount of metadata used. The default size depends on the platform.
-XX:MaxMetaspaceSize=size
Sets the maximum amount of native memory that can be allocated for class metadata. By default, the size is not limited. The amount of metadata for an application depends on the application itself, other running applications, and the amount of memory available on the system.
以下示例顯示如何將類類元數據的上限設置為 256 MB:
XX:MaxMetaspaceSize=256m
字節碼問題
ASM 5.0 beta 開始支持 JDK8
字節碼錯誤
Caused by: java.io.IOException: invalid constant type: 15
at javassist.bytecode.ConstPool.readOne(ConstPool.java:1113)
- 查找組件用到了 mvel,mvel 為了提高效率進行了字節碼優化,正好碰上 JDK8 死穴,所以需要升級。
<dependency>
<groupId>org.mvel</groupId>
<artifactId>mvel2</artifactId>
<version>2.2.7.Final</version>
</dependency>
- javassist
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.18.1-GA</version>
</dependency>
注意
有些部署工具不會刪除舊版本 jar 包,所以可以嘗試手動刪除老版本 jar 包。
http://asm.ow2.org/history.html
Java 連接 redis 啟動報錯 Error redis clients jedis HostAndPort cant resolve localhost address
錯誤環境:
本地 window 開發環境沒有問題。上到 Linux 環境,啟動出現問題。
錯誤信息:
Error redis clients jedis HostAndPort cant resolve localhost address
解決辦法:
(1)查看 Linux 系統的主機名
# hostname
template
(2)查看/etc/hosts 文件中是否有 127.0.0.1 對應主機名,如果沒有則添加
Resin 容器指定 JDK 1.8
如果 resin 容器原來版本低於 JDK1.8,運行 JDK 1.8 編譯的 web app 時,可能會提示錯誤:
java.lang.UnsupportedClassVersionError: PR/Sort : Unsupported major.minor version 52.0
解決方法就是,使用 JDK 1.8 要重新編譯一下。然后,我在部署時出現過編譯后仍報錯的情況,重啟一下服務器后,問題解決
./configure --prefix=/usr/local/resin --with-java=/usr/local/jdk1.8.0_121
make & make install
參考資料
- java8-tutorial
- Compatibility Guide for JDK 8
- Compatibility Guide for JDK 8 中文翻譯
關注公眾號:java寶典