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中也有少量独有功能。

由于是源码开放,用户可以从

http://hg.openjdk.java.net/jdk8u/jdk8u-dev将源代码clone下来自己编译OpenJDK

或者下载源码包,http://jdk7.java.net/source.html,解压后自己编译。

并且基于这些可复用的源码,诞生了很多其他版本的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包布署。

一场因OpenJDK引发的血案 之JavaFx的更多相关文章

  1. 一场由过滤器Filter引发的血案

    一场由过滤器Filter引发的血案 事件起因 本来应该是下图的登录界面 变成了这样 What's the fuck????? 抓狂 原因 解决方法: 在过滤器中给资源文件开个绿色通道

  2. [WCF]缺少一行代码引发的血案

    这是今天作项目支持的发现的一个关于WCF的问题,虽然最终我只是添加了一行代码就解决了这个问题,但是整个纠错过程是痛苦的,甚至最终发现这个问题都具有偶然性.具体来说,这是一个关于如何自动为服务接口(契约 ...

  3. dubbox微服务实例及引发的“血案”

    Dubbo 是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成. 主要核心部件: Remoting: 网络通信框架 ...

  4. Integer.parseInt 引发的血案

    Integer.parseInt 处理一个空字符串, 结果出错了, 程序没有注意到,搞了很久, 引发了血案啊!! 最后,终于 观察到了, 最后的部分: Caused by: java.lang.NoC ...

  5. Replication的犄角旮旯(六)-- 一个DDL引发的血案(上)(如何近似估算DDL操作进度)

    <Replication的犄角旮旯>系列导读 Replication的犄角旮旯(一)--变更订阅端表名的应用场景 Replication的犄角旮旯(二)--寻找订阅端丢失的记录 Repli ...

  6. Replication的犄角旮旯(七)-- 一个DDL引发的血案(下)(聊聊logreader的延迟)

    <Replication的犄角旮旯>系列导读 Replication的犄角旮旯(一)--变更订阅端表名的应用场景 Replication的犄角旮旯(二)--寻找订阅端丢失的记录 Repli ...

  7. 转:一个Sqrt函数引发的血案

    转自:http://www.cnblogs.com/pkuoliver/archive/2010/10/06/1844725.html 源码下载地址:http://diducoder.com/sotr ...

  8. 一个Sqrt函数引发的血案(转)

    作者: 码农1946  来源: 博客园  发布时间: 2013-10-09 11:37  阅读: 4556 次  推荐: 41   原文链接   [收藏]   好吧,我承认我标题党了,不过既然你来了, ...

  9. 一个字母引发的血案 java.io.File中mkdir()和mkdirs()

    一个字母引发的血案 明天开始放年假了,临放假前有个爬虫的任务,其中需要把网络图片保存到本地,很简单,马上写完了代码: //省略部分代码... Long fileId= (Long) data.get( ...

  10. form表单提交引发的血案

    最近,公司某条产品线上的一个功能出了问题:点击查询的时候,该页面在IE上直接卡死,chrome上会卡顿一段时间候提交表单进行查询.拿到这个bug单子以后,简单重现了下,基本上定位到是查询操作中的问题, ...

随机推荐

  1. python数据结构学习第一章——栈

    在这片文章中,我们使用python3.8自制一个具有基本功能的栈结构,它的功能只有push,pop,peek这三个功能 ` #!/usr/bin/env python # * coding: utf- ...

  2. 在 Debian 12 上安装 KubeSphere 实战入门

    老 Z,运维架构师,云原生爱好者,目前专注于云原生运维,云原生领域技术栈涉及 Kubernetes.KubeSphere.DevOps.OpenStack.Ansible 等. 前言 知识点 定级:入 ...

  3. 强化学习算法笔记之【DDPG算法】

    强化学习笔记之[DDPG算法] 目录 强化学习笔记之[DDPG算法] 前言: 原论文伪代码 DDPG 中的四个网络 代码核心更新公式 前言: 本文为强化学习笔记第二篇,第一篇讲的是Q-learning ...

  4. NES 模拟器中音画同步问题

    背景 模拟器是与游戏和播放器都有相似之处的系统.模拟器与游戏的相似之处,在于都需要一个采集输入--执行逻辑--然后按一定帧率(通常是 60 FPS)把画面显示出来的循环.但是模拟器又需要模拟音频设备, ...

  5. React h5架构

    目录 目录 初始化项目架构 React h5架构 工具 技术栈 搭建流程 一.Vite构建项目 二.添加 git 三.运行项目 四.配置 Eslint 校验代码 五.配置 Prettier 格式化代码 ...

  6. 《用广义CNOT门产生质数幂维的图态》

    参考文献:Graph states of prime-power dimension from generalized CNOT quantum circuit 主机文件:<2016质数图态.p ...

  7. Xshell终端连接服务器慢,问题解决方法

    Xshell连接慢的话,先在xshell中设置中点隧道然后把转发xshell的勾取消 /etc/ssh/sshd_config 里边修改第115行UseDNS把注释取消然后yes改为no 然后重启ss ...

  8. 开源 - Ideal库 - 特殊时间扩展方法(三)

    书接上回,我们继续来分享一些关于特殊时间获取的常用扩展方法. 01.获取当天的开始时间 当天的开始时间指00:00:00时刻,因此只需要获取DateTime的Date属性只获取时间即可,具体代码如下: ...

  9. C#/.NET/.NET Core技术前沿周刊 | 第 13 期(2024年11.11-11.17)

    前言 C#/.NET/.NET Core技术前沿周刊,你的每周技术指南针!记录.追踪C#/.NET/.NET Core领域.生态的每周最新.最实用.最有价值的技术文章.社区动态.优质项目和学习资源等. ...

  10. Cisco Packet Tracer 交换机代码

    二层交换机S1代码: >en #conf  t #vlan 10 #vlan 20 #int r f 0/1-5 #sw a v 10 #int r f 0/6-10 #sw a v 20 #i ...