一場因OpenJDK引發的血案 之JavaFx


https://zhuanlan.zhihu.com/p/103765203

案發現場

最近做了個項目,本地調試通過了,可在服務器上部署時卻編譯失敗,報錯如下

編譯失敗的原因是缺少javafx.util。

package javafx.util does not exist

原因分析

查看代碼,是因為使用了javafx.util中的Pair類

那為什么本地可以編譯通過了?我本看下本地jdk版本,打開一個shell窗口輸入

java --version

結果如下

再看看服務器上jdk的版本

問題浮出水面了,服務器上用的是OpenJDK。它跟本地開發環境所用的JDK還是有區別的,應該說它是一個不完整的jdk的開源版本,JDK有的東西它不一定有。具體區別體現在哪里了?

JDK與OpenJDK的區別

前世今生

JDK(Java Development Kit)是Java平台編程中使用的軟件開發環境。它包含一個完整的Java運行時環境,即JRE,以及一些Java開發工具(如javac/java/jdb等)與基礎類庫等。針對不同使用場景,其有三個不同的產品形態:

  • SE(J2SE),standard edition,標准版,是我們通常用的一個版本,從JDK 5.0開始,改名為Java SE。
  • EE(J2EE),enterprise edition,企業版,使用這種JDK開發J2EE應用程序,從JDK 5.0開始,改名為Java EE。
  • ME(J2ME),micro edition,主要用於移動設備、嵌入式設備上的java應用程序,從JDK 5.0開始,改名為Java ME。

本文講的是最常用的標准版。我們常說的JDK有兩種叫法,早期叫做Sun JDK,后來Sun被Oracle收購了,又改叫Oracle JDK,本文統稱Oracle JDK。

我們回顧下Oracle JDK的版本

  • JDK Beta - 1995
  • JDK 1.0 - 1996年1月
  • JDK 1.1 - 1997年2月
  • J2SE 1.2 - 1998年12月
  • J2SE 1.3 - 2000年5月
  • J2SE 1.4 - 2002年2月
  • J2SE 5.0 - 2004年9月
  • Java SE 6 - 2006年12月
  • Java SE 7 - 2011年7月(再次之前先將主分支作為OpenJDK 6開源)
  • Java SE 8(LTS) - 2014年3月
  • Java SE 9 - 2017年9月
  • Java SE 10(18.3) - 2018年3月
  • Java SE 11(18.9 LTS) - 2018年9月
  • Java SE 12(19.3) - 2019年3月

其中斜體版本不再支持。在開發JDK7的時候,OpenJDK已經成為JDK7的主干開發,並在2007年開源,是為OpenJDK 6。此后Sun JDK7是在OpenJDK7的基礎上發布的,其大部分原始碼都相同,只有少部分原始碼被替換掉。

其實Sun自JDK 1.5之后就開始以Java Research License(JRL)的形式公布過Java源碼,主要用於研究人員閱讀(JRL許可證的開放源碼至JDK 1.6 Update 23為止)。把這些JRL許可證形式的OracleJDK源碼和對應版本的OpenJDK源碼進行比較,發現除了文件頭的版權注釋之外,其余代碼基本上都是相同的,只有字體渲染部分存在一點差異,Oracle JDK采用了商業實現,而OpenJDK使用的是開源的FreeType。

當然,這里的“相同”是建立在兩者共有的組件基礎上的,Oracle JDK中還會存在一些Open JDK沒有的、商用閉源的功能,例如Flight Recorder,OpenJDK中也有少量獨有功能。

由於是源碼開放,用戶可以從

將源代碼clone下來自己編譯OpenJDK

或者下載源碼包,,解壓后自己編譯。

並且基於這些可復用的源碼,誕生了很多其他版本的JDK,例如IcedTea、UltraViolet都是從OpenJDK源碼衍生出的發行版,一些大公司也有自己的版本如Amazon Corretto,alijdk等。

自此OpenJDK成為由Oracle,OpenJDK和Java社區開發共同維護的單獨的一個項目,目前主要版本如下

OpenJDK 6項目 - 基於JDK 7,但經過修改后提供了Java 6的開源版本
OpenJDK 7項目 - 2011年7月28日
OpenJDK 7u項目 - 該項目開發Java Development Kit 7的更新
OpenJDK 8項目 - 2014年3月18日
OpenJDK 8u項目 - 該項目開發Java Development Kit 8的更新
OpenJDK 9項目 - 2017年9月21日
JDK項目於2018年3月10日至20日發布
JDK項目於2018年9月11日至25日發布
JDK項目發布12 - 穩定階段

可以說OpenJDK是自jdk7版以來Java標准版的官方參考實現。它和Oracle JDK的主要區別如下:

OpenJDK不包含Deployment(部署)功能

部署的功能包括:Browser Plugin、Java Web Start、以及Java控制面板,這些功能在OpenJDK中是找不到的。

OpenJDK源代碼不完整

這個很容易想到,在采用GPL協議的OpenJDK中,SUN JDK的一部分源代碼因為產權的問題無法開放給OpenJDK使用,其中最主要的部份就是JMX中的可選元件SNMP部份的代碼。

部分源代碼用開源代碼替換

出於產權的問題,很多產權不是SUN的源代碼被替換成一些功能相同的開源代碼,比如前面跳到的說字體渲染部分的實現在OpenJDK中使用Free Type代替。

OpenJDK只包含最精簡的JDK

OpenJDK不包含其他的軟件包,比如Rhino Java DB JAXP……,並且可以分離的軟件包也都是盡量的分離,但是這些大多是自由軟件,你可以自己下載安裝。包括這里遇到的javafx,也可以自己下載安裝到openJDK的類庫中。

功能上

應該說,兩者之間超過99%的功能都是相同的,細微的區別在於Oracle JDK具有Flight Recorder,Java Mission Control,Application Class-Data Sharing 功能以及更多的垃圾收集選項和更好的渲染器,而OpenJDK具有Font Renderer功能。




許可證

Oracle JDK:GPL(通用公共許可證)

OpenJDK:GNU,GPL

在沒有商業許可的情況下,在2019年1月之后發布的Oracle Java SE 8的公開更新將無法用於商業用途。但是,OpenJDK是完全開源的,可以自由使用。正因如此,一般服務器上用的都是OpenJDK。

穩定性

Oracle JDK構建過程是基於OpenJDK的,所以他們之間並沒有技術差別。只是OpenJDK由於版本發布比較頻繁,可能會遇到不穩定的問題。根據社區反饋,也有一些OpenJDK用戶遇到了性能問題。而Oracle JDK作為商業軟件,在穩定性方面要好很多,或許OpenJDK就是給Oracle JDK踩坑用的吧,哈哈。

解決辦法

這里的javafx.util包在jdk 1.8的類庫里面有,但在OpenJDK 8里面是沒有的,所以引發了上面的編譯錯誤。解決方式也很簡單,主要如下幾種做法:

  1. 不要使用javafx.util這種OpenJDK里面沒有的包;
  2. 本地開發環境直接使用OpenJDK,或者部署時服務器或者容器上使用與本地開發環境版本一致的Oracle JDK,但這會涉及到版權問題;
  3. 下載javafx-sdk到服務器,編譯時將javafx-sdk位置作為--module-path參數傳入;l
  4. 在pom里面顯式添加javafx依賴,這樣在服務器上用mvn編譯時,會把它從maven中央倉庫拉到本地打包到你的工程里。
<!-- https://mvnrepository.com/artifact/org.openjfx/javafx-base -->
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-base</artifactId>
    <version>14-ea+7</version>
</dependency>

4. 本地編譯好,直接用jar包布署。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM