Blog chevron_right 未分类

准备迁移至 OpenJDK 新发行版

如果不了解每个环境中有哪些 Java 应用程序、框架、平台和工具在运行,以及它们所使用的 Java 版本和操作系统,怎么可能提出切合实际的预算和时间表?尽管如此,许多组织仍要求开发人员在开始评估其 Java 资产之前敲定拟议预算并确定时间表。

为了成功地进行迁移,组织应与 SAM 团队、应用程序所有者和合规部门携手并进。这种团队协调将进一步明确 OpenJDK 包的实际部署(执行)和测试(验证)期间要完成的工作,有助于避免先有鸡还是先有蛋的问题。   

迁移方法术语 

以下是我们在本文中用来描述迁移方法和详细信息的一些常用短语和术语:

短语 定义
补偿措施或步骤 在迁移项目进行期间为克服各项挑战而必须执行的众多额外操作,例如额外的第三方产品安装和配置。  
焦点团队 迁移项目专门团队,通常由项目经理、IT 架构师和 Java SME(主任工程师)组成。 
存储桶分类 Java 运行时/SDK 安装会被添加到称为存储桶的特定迁移组/集。存储桶可以根据特定的项目约束和/或特性来命名,但通常遵循相同的标准:看起来像垃圾、需进一步调查、绑定至某产品和迁移就绪。
空运行执行/方法 快速执行过程,只需极少环境更改和准备,例如迁移执行快速切换。
健全性检查或健全性测试 快速基础架构测试,用于验证应用程序是否在目标环境中运行,例如,AppServer 是否已启动,应用程序是否正加载其第一个页面而没有错误?
快速切换 使用符号链接快速更改为 OpenJDK,无需安装运行时。用于快速验证迁移(健全性检查)。
质量度量标准 用于评估项目运行状况的迁移内部指标。这些度量标准通常与非功能性需求相关,例如性能指标。
表 1 –常见迁移方法术语

成功实施迁移项目所需活动速览 

  1. 组建迁移“焦点团队”。即获选执行迁移项目的专门团队,通常由一名 PM、一名 IT 架构师、一名 SAM 工程师和若干名可根据需要加入项目团队的 SME 组成。
  2. 清点 Java 资产。FS 爬虫工具是更好的选择,因为 Java 运行时的使用不需要将包管理器部署到服务器平台和桌面。 
  3. 重要事项:使用脚本对安装路径快速分类。通过对安装路径进行快速分析,可以确定(推断)与 Java 运行时绑定的产品。 

注:99% 的 FOSS 产品和发行版都支持某些版本的 OpenJDK。通过对 Java 运行时安装进行如上所述的快速 FS 分类,可以将这些产品归类为“迁移就绪”。唯一缺少的是定义迁移过程,例如,Solr 完全 OSS 并支持 OpenJDK,对环境的影响和改变“最小”。 


  1. 确定应用程序所有者和环境管理者。应用程序详细信息对于产品分类至关重要。更多详情将在稍后介绍。 
  2. 确定特定产品的 SME。某些产品需要特殊配置才能执行。在大多数情况下,对环境进行简单更改即已足够,例如更改 JAVA_HOME 环境变量。 
  3. 进行应用程序审查内部组件架构。对应用程序进行分类可以采取多种方法,而团队站立会议是获取应用程序内部信息的最快、最可靠的方法。通常情况下,针对一组选定应用程序(即最有可能发挥关键功能的应用程序),1 小时站会足以收集有关应用程序架构的详细信息。目标受众通常是应用程序架构师或 QA 工程师。可以通过初始问卷调查为站会提供信息。 

:收集“功能性”详细信息并不重要,只需收集组件架构,例如,应用程序是否在服务器端生成 PDF 报告?


  1. 应用程序和产品详细信息 – 分类属性。部分应用程序需要特定的配置,但大多数应用程序都使用通用的 Java 标准。分类属性是用于运行产品的特定 OpenJDK 要求,例如,将自定义 CA 添加至 OpenJDK carcerts 文件、环境变量配置或基于操作系统的更改,例如安装缺少的库。     

:可运用相应技巧来快速获取所需信息,包括分析操作系统进程表和层次结构。 


  1. 准备存储桶分类。第一级存储桶分类附带自动化功能(即 FS 分析),可快速将 JVM 安装分发至不同的域中。最后的工作是将目前为止的详细信息整合至最终的存储桶分类中,并将每个 JVM/产品安装详细信息设置为分类属性。简单示例: 
  • 清单数据:Oracle JRE 版本 11.0.11。 
  • 存储桶分类:迁移就绪。 
  • 分类数据:打包在 EAR 文件中的常规 JEE 应用程序。 
  • 分类属性:操作系统:Linux RedHat Enterprise 8.9 版。AppServer 使用 JAVA_HOME 环境变量来确定需要使用哪个 Java 运行时。Java 运行时在名为“appserver”的用户配置文件中进行配置,Java 环境详细信息(例如 Path、CLASSPATH 等)均位于该用户根文件夹下名为“.java”的文件中。该配置文件由用户根文件夹下名为“.bash_profile”的另一个配置文件调用。这不是基于 pacman (RPM) 的安装;需要解压缩和手动配置(多用途服务器)。 
  • 分类 MISC 数据:应用程序使用在 Nexus 中实现的 Maven 专用存储库解析其所有的库依赖关系。 
  • 验证详细信息:大多数应用程序功能性测试均使用 Protractor 自动进行。 
  • 附加信息:应用程序部署和 Java 运行时配置使用 Jenkins 管道完成 – 需要进行更改,以将 OpenJDK 部署包含在应用程序 CD 管道中。 
  1. 构建迁移数据仓库。尽管并非必需,但将分类详细信息分解为特定实体(或多维数据集)可能有助于在迁移期间和之后生成快速报告和进行数据整合。 
  2. 确保所有许可产品都已取得实际许可。大多数 Oracle 产品都附带用于应用程序的嵌入式 Java 运行时许可1。开发人员通常拥有本地管理员权限,可直接从 Oracle 网站下载这些 Oracle 产品(例如 Oracle RDBMS)。Java 运行时具有 Oracle 产品许可并不代表该产品已获得许可(例如 Oracle 即时客户端)。合规团队(IT 治理)应当能够帮您对这些情况的清单进行快速分析和分类。 
  3. 执行应遵循三阶段流程:快速切换、提交更改、Java 运行时移除。更多详情将在下文介绍。 
  4. 进行内部审计。执行首批迁移后,在迁移环境中安排定期审计十分重要。可使用 SNOW 或 Flexera(Oracle 在审计期间的常用工具)检索这些信息。 
  5. 验证和人体工学测试策略。QA 工程师通常遵循非常严格的流程来验证应用程序更改或新特性。可将从 Oracle JDK 切换至 OpenJDK 视为操作系统补丁更新。在回归测试中,通常不会“完整”运行应用程序 E2E 场景,只需验证健全性检查和一些选定的核心功能,该过程称为冒烟测试。在某些情况下,对于低优先级、FOSS 存储桶分类的 JVM 产品(例如 Solr),只运行健全性测试即已足够,例如确保产品在启动时没有任何问题。 
  6. 稳定化阶段。该阶段为迁移后的阶段,此时应监测所有已迁移环境,以发现在执行和验证期间并未出现的问题。 

迁移准备 

类似的产品会具有相似的功能性和可用性,因此可对大多数基于 Java 的系统进行组合,将其分类为应用程序组。这些组的分类很重要,因为它可用于整合外部 OpenJDK 安装所需的针对特定应用程序的过程。现今的大多数服务器产品都为 OpenJDK 提供非常清晰的路径。应在发现阶段收集这些步骤,例如 Claris FileMaker 等 OpenJDK 特定产品过程。 

对于需要额外步骤的情况,例如安装 IcedTea-Web 等第三方软件,存储桶分类属性对于进行验证和在最佳时间执行迁移非常重要。这意味着如果对 OpenJDK 下运行的单个应用程序运行具有补偿步骤(分类属性中定义的特定产品过程)的安装脚本,将足以对环境组中定义的“所有”其他应用程序提供样例3。因此,用于这些其他环境的其余步骤可以概括(总结)如下:  

  1. 记录迁移期间所采取的过程
  2. 对环境组中的所有其余应用程序复制这些过程

应用程序分类还应按照用途(例如无缝/关键/未来)、类型(例如集成中心、AppSever)和版本控制来定义。在实践中,一旦在组内发现一台服务器(即空运行配置),即可将其余所有配置轻松复制到所有其他服务器(完全部署)。 

简单示例:分布在 10 个关键平台上的 10 个节点的 ELK 8.5(版本控制和类型)集群必须仅在一个节点(用途)中验证一次。所有其余九个节点皆可照搬特定 OpenJDK 迁移期间使用的相同技术和过程。集群配置在“应用程序”级别进行定义,而非“OpenJDK”级别。无需在 JVM 级别验证集群配置甚至网络配置(例如 VIP、VMAC、IPSec 等)。

另一项重要因素是 OpenJDK 风险矩阵分类。一些非常具体的迁移案例必须根据旧版本 Java SE 迁移期间发现的这些常见问题来定义补偿措施。大多数服务器/桌面迁移不需要这些补偿措施,但其主要目的是减轻相关风险,保证 Oracle JDK 和 OpenJDK 之间的所有转换尽可能无缝进行。

减轻这些 OpenJDK 风险的最佳方法是使用 OpenJDK 风险评估矩阵,详见下文。但如果未提供该选项,则可使用其他技术来评估应用程序的用途和特性,包括: 

  • JDK 版本分析。(例如,JDK11+ 不支持 Java Web Start 或 Applet,其中没有风险)
  • Java 包内省。(例如,分析 JAR/WAR/EAR 文件的库依赖关系,包括 XML 配置、spring 属性文件、YAML 文件等)。用例示例:如果应用程序将 JNLP 配置文件定义为其 WAR 包的一部分,它将支持 Java Web Start,这意味着该应用程序提供的所有桌面都应在配置 ITW 的情况下迁移。
  • 应用程序名称和版本。通过了解 OOTB 产品名称和版本,可以推断库依赖关系并提前规划可能的解决方法。示例:Solr 8 仅使用标准 Java 运行时 API,也就是说无需任何额外步骤(补偿措施)即可迁移至 OpenJDK(无缝存储桶分类)。此外,通过对服务器上运行的所有实时 Java 进程进行自检,清单工具可以轻松获得一些实用技巧,比如生产中的应用程序列表。 
  • 高级用户(选定用户)访谈。对于桌面,确定应用程序的关键用户可以帮助提供在这些环境中使用的 Java 产品和特性的样例。 
  • 应用程序文档。来自内部文档存储库的信息有助于明确特定的 Java 应用程序用途和特性,例如 Javadoc、用户手册等。 
  • 内部应用程序存储库。分析组织范围的工件存储库(例如 Nexus 或 SonarQube)可以帮助确定针对特定应用程序的需求和依赖关系(例如 Maven pom 文件)。 

当信息可能不足以识别这些风险时,由于缺少信息,也就无法直接缓解这些风险,您可在迁移之前采取预防性措施,例如在服务器端安装 Monotype 字体。这些措施的决策主要基于 Java 应用程序及其服务器配置的样例。

迁移方法

分类从应用程序团队研讨会开始。

在清单分类期间,确定 Java 资产中识别出的中每个服务器/桌面环境的管理者非常重要。将环境与其权利所有者(即应用程序所有者)进行关联,有助于快速确定迁移利益相关者。 

例如,假设您安装了系统范围的 JDK,并将应用程序配置为使用此 JDK。在运行清单工具时,清单将不会反映使用此独立 Java 运行时的应用程序。 

让利益相关者聚集在同一房间里,也可以是线上虚拟会议室。会议参与者通常包括产品经理和应用程序架构师,可能还包括应用程序所有者和高级用户,视组织规模和结构而定,少则二人,多则十几人。至少有必要与每个相关应用程序团队举行一次会议。 

这些团队会议(在敏捷模式中通常称为团队研讨会)的目的在于尽可能多地收集有关应用程序非功能性需求和组件架构的信息。理想情况下应准备一组整合的节点和组件图及文档,后续流程中需要借助这些文档来对 Java 迁移中涉及的应用程序进行分类。

每个组织都拥有自己的开发生命周期策略。OpenJDK 迁移是一种基础架构软件,这代表应用程序测试的常规惯例需要进行调整,来为迁移提速。以下是一些重要的详细信息: 

  • 每项功能性(例如冒烟、UAT)和非功能性(例如性能、安全性)测试应仅在较低平台环境(例如 SIT/QA)中执行一次。如果符合度量标准,升级至更高平台应无缝进行 – 验证期间也可确定额外的补偿措施。 
  • 测试用例应当尽可能自动化。Azul 提供一项工具来帮助运行健全性检查以及快速功能性测试(冒烟测试)。该工具以 Docker 映像的形式提供。 
  • 一组集群中的节点通常具有相同的配置、应用程序和 Java 运行时配置,只需要以空运行方法测试其中一个节点。
  • 例如,如果集群环由 10 个配置相似的节点组成,应仅选择一个节点进行验证,通常选择主节点。如果验证通过,环中所有其余节点即可无缝迁移。 
  • 集群级别的配置(热位数、热切换、热备用等)在应用程序级别而非 JVM 级别进行处理,也即此处应用的是与其他环境中的测试相同的策略。
  • 由于我们不测试应用程序功能性,仅测试应用程序基础架构,因而一组简单的回归测试应当足以对迁移进行验证。以下是每种测试用例的推荐测试类型:
  • 适用于桌面应用程序的 UAT(仅限胖客户端,例如 Applet 或 JFX 应用程序) 
  • 适用于应用程序功能性快速验证的冒烟测试 
  • 性能测试(负载和压力),前提是已签署相应的性能 SLA。 
  • 迁移后立即进行快速健全性检查,例如检查应用程序是否正确启动、应用程序初始化后所有 TCP/IP 端口是否均在线等 
  • 适用于 JDK 158 及更低版本的安全测试。黑盒测试足以验证 Java 内部安全配置。如果并未对 Java 运行时(安全管理器)进行安全更改,则不考虑对 OOTB JVM 安全配置下运行的应用程序进行测试 – 无缝迁移存储桶。 

非功能性需求包括开发环境、性能 SLA、HA8 配置、产品和版本等。


如果某些团队无法参加会议,您也可要求应用程序团队填写问卷或完成调查,以便了解当前 Java 封装。下面我们举例说明。

问题 重要性
您采取何种应用程序部署策略?是客户端应用程序还是服务器应用程序? Java 构建因操作系统而异,明确应用程序在哪种操作系统上运行,有助于我们了解需要提供哪些 JRE/JDK 构建用于评估、测试和部署。
如果是服务器应用程序,它是否在应用程序服务器上运行?Java EE 是否在服务器上运行? 由于 Java EE 应用程序的自定义特性,它们可能需要额外的配置,例如,Jasper 等特定库可能需要额外的服务器配置,包括在服务器端安装 Monotype 字体以处理所生成映像或 PDF 的文本。 
如果是客户端应用程序,您的应用程序使用 Applet 还是 Java Web Start?  这可以快速帮助您确定用来准备环境的补偿措施,例如,Web Start 使用 DRS。
您的应用程序是否支持 TLSv3? TLS 1.3 仅可在 261 版更新之前的更新中作为 OpenJSSE 的一部分适用于 OpenJDK 8,因为 OpenJDK 11 具有向后移植兼容性,这也是将其用于某些早期版本的唯一方法。不过,最新版本的 JDK 8(主要是 261 版更新)即使没有 OpenJSSE,也能通过简单地切换一些内部 JVM 配置来支持 TLS 1.3。
您的应用程序是否生成 PDF 报告、图像、二维码或使用图形 API?如果是,所用框架的名称是什么? 生成报告、常规意义上的图像或任何其他图形组件时会使用 2D 或 3D 的 Java 图形 API。该图形 API 要求在服务器端安装字体包。兼容性工具包 Azul CCK 用于解决 Java 8 缺少这些组件的问题。
表 2:应用程序团队问题与解答

这些问题的目的在于尽可能多地收集与所讨论应用程序相关的信息。 

尽管此步骤可能看起来与建立清单类似,但这些团队会议将在迁移流程中发挥关键作用。为启动风险识别并采取补救措施,您需要每个应用程序的整合视图。应用程序所有者可能做不到对组织整个基础架构知根知底,但他们了解组织应用程序的约束。此步骤有助于编译创建 Java 资产的全面视图所需的信息,而建立清单则可能无法提供所需的全部信息。 

较低环境中的清单和分类遵循与受控环境相同的流程。生产环境可能不像较低环境(例如开发环境)那样与应用程序所有者直接关联,但必须像以前一样与应用程序关联。关键区别在于针对这些情况,可能需要更多利益相关者加入会议,包括 IT 管理员和 DevOps 专家。我们建议并行举行这些研讨会,但较低环境的要求可能与较高环境(例如预发布)的要求不同。对于这些情况,分类属性必须合并过程变更,作为迁移的附加要求。例如,开发环境使用单用途配置,其中单个 Java 运行时配置用于测试,而生产环境使用多用途配置,其中 Java 运行时的多个实例使用单个配置文件(基于用户的安装)进行配置。

OpenJDK 补丁更新策略 

即便可以通过应用程序团队会议更为全面地了解您当前的 Java 资产,建立详尽的清单对于实现成功迁移仍然具有关键作用。 

如果贵组织与我们合作过的其他组织一样,Java 应用程序的部署已有时日,甚至可能从组织成立之初便已开始,那么在一般情况下,您部署的新应用程序会使用当时的最新版 JDK,之后即使又发布新版 Java,也会继续使用既有版本。如果应用程序正常运行,则无需持续更新 JDK 版本。只有在安全补丁和漏洞修复对所用版本不再适用时,才需要升级 Java 版本。这是较低环境中 Java 运行时版本相对久远的主要原因之一,可能会带来一些问题。 

在较低环境中,Java 运行时通常作为 CI/CD 管道的一部分与应用程序一同部署。应用程序所有者通常可以完全控制这些环境中的整个自动化过程。由于应用程序使用 Java 运行时加以修补,通常当这些自动化管道达到稳定后,代码库更改即成为这些环境中引入的唯一更改,而 Java 包(版本)不会发生任何更改。也就是说在大多数新应用程序部署中(例如新 Docker 映像或部署到生产环境),这些环境的小型维护补丁不会附带 JVM 补丁更新 (CPU/PSU)。 

在迁移项目期间,不妨将这些管道分离或参数化,以便始终及时获取 OpenJDK 的最新补丁更新(即 CPU)。这项工作可能需要其他团队参与,包括 IT 管理员、DevOps 架构师、信息安全或治理人员。


注:另外需要注意的重要一点是,基于操作系统的 OpenJDK 发行版(其他发行版)可能没有可用的最新补丁,特别是对于旧有 Linux 发行版,即 Vault 发行版。如果使用 pacman 来配置环境,请务必确保发行版的 OpenJDK 存储库已正确配置或添加至您的环境,例如 https://docs.azul.com/core/zulu-openjdk/install/rpm-based-linux。这将有助于您加速实施补丁更新策略。


使用最新补丁确保 Java 运行时的安全可能并非大多数应用程序的优先事项,这是旧版“稳定”应用程序构建通常使用过时 JDK 版本的原因。因此,将补丁更新控制从应用程序部署策略分离到 IT 管理策略始终是明智的做法。

使用资产管理工具 

要创建 JDK 使用情况的完整清单,请检查运行任何基于 JVM 的应用程序的每台计算机。可采用多种基于市场的 IT 资产管理工具来清点您的 Java 资产。部署这些工具通常是为了确保企业遵守许可条款和条件。 

我们发现这些工具的常见问题是它们不一定能提供项目所需的全部必要信息,有时它们只提供基于包安装的信息,特别是在 Windows 平台上,例如 Windows 中的 MSI 或基于 Linux 的安装中的 Pacman。由于 Java 原则上是独立的环境,因而只需对其中的包进行解压缩,即可确保 Java 运行时正常工作。这意味着要清点环境中的所有服务器和桌面,可能需要进行额外的努力。  

我们推荐使用“FS 爬虫工具”方法来搜索环境中可能存在的所有 Java 包安装。这么做是因为有时应用程序偏好于将 Java 运行时与应用程序安装/部署一起打包。在这些情况下,大多数 SAM 工具无法识别应用程序和 ISV 产品中的 Java 安装。 

一般说来,对于清单中的每个条目,理想状态是包含有关 JDK 的以下详细信息: 

  • FQDN:用于未来分类的完全限定主机名。 
  • 类型:物理机(指出它是服务器还是桌面同样很有帮助)、云实例或容器。 
  • 访问详细信息:用于通过网络连接访问物理机或云实例的凭据,这些凭据具有足够的权限以允许安装 JDK。  对于容器来说,这些详细信息与容器映像的生成方式有关。  这可能通过 CI/CD 工具实现,并且应当包括允许配置不同 JDK 以将其纳入映像的信息。 
  • 操作系统:使用的操作系统以及其他详细信息。  通常会选择 Windows、Mac OS 或 Linux,更多信息还包括所使用的版本,特别是对于 Linux 需注明具体发行版,以便可以选择正确的安装格式。最后,由于某些机器可能运行旧版操作系统,应留意其架构为 32 位还是 64 位。 
  • 安装类型:可采用几种不同的方法来安装 JDK,包括系统范围安装、用户特定安装乃至自定义包安装。 
  • 自定义应用程序配置类型:对于指示 JDK 如何与应用程序一起使用非常重要。 
  • 应用程序名称:关联条目,应当用于识别使用当前 JDK 包的所有可能的应用程序。大多数情况下为 1:1 关系。 
  • JDK 版本:还应包括已安装的更新级别,例如 JDK 8u202。 
  • JDK 位数:即使运行的是 x64 计算机,某些应用程序也需要 32 位运行时安装。 
  • JDK 路径:应用程序的安装路径。这条信息非常重要,可用于稍后在迁移流程中对绑定 JDK 安装进行分类。 
  • 产品详细信息:采用 JDK 安装分类的所有产品的名称。 
  • 环境详细信息:用于系统范围和基于用户的定义的 JAVA_HOME、CLASSPATH 和 Path 环境变量。可提供有关如何对环境进行配置的重要详细信息。 
  • Windows 注册表项:JavaSoft 注册表信息,其中包含安装路径、活动 Java 配置和已安装 Java 包列表。 
  • JDK 发布者:JDK 提供者的实施者,例如 Oracle Corporation。这对于标出哪些 OpenJDK 提供者应标记为迁移/不迁移非常重要。 
  • 许可信息:一些 JDK 包附带发布信息,指示分配给包安装的许可,即商业许可。 

我们建议在第一阶段使用 ITAM 工具,从清单中收集原始数据。ITAM 非常适合广泛分类的第一阶段,而我们下一步将引入对这些存储桶的手动分类,提供更深入的分析并确保严谨操作。以下是我们根据与客户往来的经验给出的参考建议。 

利用来自应用程序团队研讨会的信息,将原始数据移至存储桶内。您可以使用符合自身需求的独特存储桶,也可选择以下存储桶:

自动存储桶样例 手动存储桶样例
可能迁移 迁移就绪 
需进一步澄清  迁移就绪 
绑定 JDK 标记为移除 
未使用 标记为移除 
看起来像垃圾 
表 2:自动和手动存储桶样例

我们暂停片刻,来谈谈平台环境(即测试、集成、开发),这些环境可能不像受控环境(即 QA、预发布、生产)那样具有明确的定义和组织。评估平台环境时应格外小心,因为某些位置经常会有一次性安装,只是简单地解压缩或复制 Java 运行时,而并未进行适当 QA 或予以记录。如果您的 ITAM 系统仅提供打包安装信息,例如来自 MSI 安装或来自 RPM 数据库,那么遍历 FS(爬虫工具)可能是这些情况下的唯一选择。 

JDK 提供的工具有助于快速识别 Java 封装分类期间可以使用的重要信息。可通过多种方法来检索 JDK 信息,包括分析 JDK 发行版的“发布”文件、检查 Windows 注册表、使用 JEP 223 (java -version/-showversion/-fullversion)、Python 脚本(如“jcheck.py”)、java 系统属性、jcmd/jmap 等。我们的首选方法是直接从 Java 运行时检索这些信息,例如使用“java.vendor”系统属性来查找 OpenJDK 发布者。 

还有一种有助于对清单数据进行初步分类的巧妙方法,就是在大多数情况下,默认绑定 JDK 安装是产品安装路径的一部分。做到这一点有几种方法,一种快捷的方法是在清点期间定义“分类模式”来推断出哪个产品链接到哪个 JDK。为实现此目的,您可在完成清点后进行快速手动分析,也可在发现期间应用基于模式的正则表达式。 

以下是一些可能用到的正则表达式(基于 POSIX 的正则表达式)示例,可用于快速映射 Linux 上的 Oracle JDK 产品安装(以行分隔):

r|opt|[Vv][0-9]+)\/.*[Oo]racle\/.*dbhome_?[0-9]+\/.*[Jj]([Rr][Ee]|[Dd][Kk]).* 

.*\/(us?r?[0-9]+|usr|var|opt|[Vv][0-9]+)\/.*[Oo]racle.*\/(product|agent(_[.0-9]+)?|[Oo][Pp]atch){1,}\/.*[Jj]([Rr][Ee]|[Dd][Kk]).* 

.*[Uu][0-9]+.*(\/|\\\\)[Oo][Rr][Aa]([Ii]nventory)?.* 

.*\/[Oo][Rr][Aa].*((\/|\\\\)[Mm][Ii][Dd][Ll][Ee][Ww][Aa][Rr][Ee])?.* 

^\/(opt|usr|var|(u[0-9]{1,2})).*\/([Oo][Bb][Ii][Ee][Ee]){1,}.*[\.\-0-9]*.*\/[Jj]([Rr][Ee]|[Dd][Kk]).* 

.*(\/[Oo][Rr][Aa])?.*\/([Mm][Ii][Dd][Dd][Ll][Ee][Ww][Aa][Rr][Ee])?.*([Ww][Ll][Ss]([Ee][Rr][Vv][Ee][Rr])?).*(\/[Ss][Oo][Aa].*)?.* 

.*[Oo]racle.*[Gg]rid.*

这些表达式不仅有助于迅速推断 JDK 的用途,还有助于快速对 JDK 绑定的产品进行分类。在上面的示例中,可以找到典型的 Oracle 产品安装。通过一段脚本可在已清点 Java 资产之上评估这些表达式,并将匹配的表达式快速分类为“Oracle 产品的 Java 运行时”。

Prepare to migrate to a new OpenJDK distribution by classifying the raw data from your inventory.

清点完毕后,即可创建“迁移存储桶”来组织清单中的组件并确定其优先级。 

第一个存储桶是分类的第一步,用于快速识别可从资产中过滤出哪些 Java 运行时。所有标记为与产品绑定的 JDK(例如上文中通过模式匹配给出的 JDK)都应放入“请勿迁移”存储桶,因为它们已获得 ISV 许可。所有其他 JDK 则应放入“需进一步澄清”存储桶。 

该流程可能会移除清点期间发现的大量安装。完成第一次迭代后,请注意对于 Windows 和 Linux,系统范围的安装通常具有相同的模式。这两种环境中的包安装(即 MSI 和 RPM)在安装路径、Windows 注册表项、符号链接等方面都遵循相同模式,全部可用于将这些 JDK 从“需进一步澄清”存储桶移至新存储桶,可将其命名为“可能迁移”。对于这种情况,可以使用与前述安装模式(正则表达式)类似的技术。 

通过分析每个无关条目的安装路径,您可以轻松填充“看起来像垃圾”存储桶。以下是应将哪些包添加至垃圾存储桶的一些示例: 

  • C:\$RECYCLE.BIN\S-1-5-21-725345543-131490\$R7POJLW.0_271\jre 
  • /u01/app/oracle/oem13c-decommissioned/agent_13.4.0.0.0/oracle_common/jdk 
  • /oracle/Middleware/Oracle_Home/oracle_common/jdk/jre.bkp 
  • C:\Program Files\Java\jdk13.0.1.bkp 

您已填满初始存储桶,但仍需按照 JDK 安装计数继续对“可能迁移”存储桶中的独立 JDK 包进行分类。封装中的 Java 运行时数量取决于清单的准备方式(例如通过遍历文件系统完成)和被分析的平台(即 Windows 和 Unix),但在某些情况下,数字可能并不符合“现实”。需要进行第二级过滤,以确定正确的安装计数。要完成此操作,需要遵循以下思路: 

  • 来自某些 JDK 提供者(例如 Oracle)的 MSI Windows 安装会在路径“C:\Program Files\Common Files\”(通常称为“javapath”)下为已安装的 JDK 创建符号链接。该符号链接指向实际 JDK 安装,只是一种快速映射至 Windows 注册表 CurrentVersion 键中所定义条目的简单方法。 
  • Java 开发工具包 (JDK) 通常附带内部定义的 Java 运行时环境 (JRE) 版本。JRE 的使用存在限制,并受特定许可条件约束,例如仅用于开发目的,因而在此需要特别注意合规性。 
  • 安装 Java 开发工具包 (JDK) 时,可以选择安装或不安装 JRE。默认情况下安装在与 JDK 相同的结构中,不过并无一定之规,实则亦可放在其他位置。在这些情况下,应将 JRE 视为独立于 JDK 的 Java 运行时安装。 

我们以功能性示例来说明,下方给出的示例是 Windows 上相同 Java 运行时安装的一部分,也即它们代表同一 JDK 的“单个”安装而非“多个”安装: 

  • C:\Program Files\Common Files\Oracle\Java 
  • C:\Program Files\Java\jdk1.8.0_221 
  • C:\Program Files\Java\ jdk1.8.0_221\jre 

要完成该初始发现阶段,请在“可能迁移”存储桶中创建额外的清点阶段,用于标记所有系统范围的 JDK 安装。通过分析 Windows 注册表中的 JavaSoft 空间并对 Linux 的 pacman 存储库运行查询(例如 rpm -q 类型的指令),可以轻松完成此操作。系统范围的分类应用程序应在存储桶内进行标记,因为它们很可能已准备好进行迁移。 

至此清点完毕,您已准备好进入发现的第二阶段,也即对所有正在运行的 Java 应用程序进行分类。该阶段不仅有助于澄清正在运行的应用程序,还可以确定预期软件版本和活动版本之间可能存在的差距。 

测试执行策略(验证阶段) 

每个组织都拥有自己的开发生命周期策略。OpenJDK 迁移是一种基础架构软件,这代表应用程序测试的常规惯例需要进行调整,来为迁移提速。以下是一些重要的详细信息: 

  • 每项功能性(例如冒烟、UAT)和非功能性(例如性能、安全性)测试应仅在较低平台环境(例如 SIT/QA)中执行一次。如果符合质量度量标准,升级至更高平台应无缝进行 – 验证期间也可确定额外的补偿措施。 
  • 测试用例应当尽可能自动化。 
  • 一组集群中的节点通常具有相同的配置、应用程序和 Java 运行时配置,只需要以空运行方法测试其中一个节点。 
  • 例如,如果集群环由 10 个配置相似的节点组成,应仅选择一个节点进行验证,通常选择主节点。如果验证通过,环中所有其余节点即可无缝迁移。 
  • 集群级别的配置(热位数、热切换、热备用等)在应用程序级别而非 JVM 级别进行处理,也即此处应用的是与其他环境中的测试相同的策略。 
  • 由于我们不测试应用程序功能性,仅测试应用程序基础架构,因而一组简单的回归测试应当足以对迁移进行验证。以下是每种测试用例的推荐测试类型:  
  • 适用于桌面应用程序的 UAT(仅限胖客户端,例如 Applet 或 JFX 应用程序) 
  • 适用于应用程序功能性快速验证的冒烟测试(回归)。 
  • 性能测试(负载和压力),前提是已签署相应的性能 SLA 作为质量度量标准的一部分。 
  • 迁移执行期间进行快速健全性检查(例如检查应用程序是否正确启动、应用程序初始化后所有 TCP/IP 端口是否均在线等) 
  • 适用于 JDK 1511 及更低版本的安全测试。黑盒测试足以验证 Java 内部安全配置。如果并未对 Java 运行时(安全管理器)进行安全更改,则不考虑对 OOTB JVM 安全配置下运行的应用程序进行测试 – 无缝迁移存储桶。 

测试套件配置示例 

此处应给出特定应用程序的全套测试用例,不过仅列出用于验证核心应用程序功能性的相关测试用例。示例列表:

应用程序名称 测试用例 测试类型 备注
B2B Web 应用程序 TC01验证登录 
TC02验证产品搜索 
TC03生成客户报告 
冒烟测试 结合使用 Azul 的 MigTester 与 Protractor 测试套件 
搜索引擎 TC01快速产品搜索 冒烟测试  
表 2:测试套件配置示例

迁移稳定化  

稳定化是一项迁移后的活动。它由一组监测活动来定义,用于识别迁移结束后应用程序环境可能存在的不一致(验证期间未捕获的问题)。这些活动是被动操作,应与迁移团队和每个应用程序团队合作执行。主要包括: 

  • 监测 ServiceDesk 票证中是否存在 Java 应用程序错误(主要针对桌面): 
  • 定期检查基准应用程序功能性。 
  • 定期对服务器日志进行抽查以找出无关错误。 
  • 定期采访选定的应用程序用户,以了解可能存在的运行时不一致情况。 

迁移结束后,达到稳定通常需要一个月左右的时间。稳定期间出现问题很少见,通常表明迁移期间缺少补偿步骤。制定计划,以尽快获取最新 CPU 版本。 

除了迁移参与团队会在迁移之前协助识别这些问题之外,Azul 还提供 24x7x365 支持,旨在帮助解决迁移部署结束后可能出现的任何异常情况。 

配置后迁移 

“同类”迁移完成后,需要考虑对安全性进行深度分析。该分析的主要目的是识别当前运行的 Java SE 版本中可能存在的严重漏洞。  

升级不应更改主要版本(例如 Java 8 到 11),而应仅关注次要版本更新(例如 8u201 到 8u382)。由于从非常老旧的版本迁移至较新构建版本可能显著影响服务水平,可以采取循序渐进的阶梯策略。 

解决此问题的一种方法是找到最近的累积 CPU 包,其中含有大多数关键 CVE12(评分 9+),使该包达到稳定,最终循序渐进地上移,直至迁移至最新版本。该流程可能耗时数月,具体取决于服务器数量以及旧版本号的 Java 安装。 

每当发布新补丁更新,可能都需要对 JVM 进行调优,以符合现有 SLA(例如安全性、性能等)。在理想实践中可比照待部署目标 Java 版本,根据确定的得分较高的 CVE 数量对 Java SE 版本进行分类。

JAVA 版本 安装数量 发布日期 CVE 导入数量
1.8.0_20 3 2014 年 9 月 10
1.8.0_45 2 2015 年 4 月 24
1.8.0_60 18 2015 年 8 月 25
1.8.0_65 2 2015 年 10 月 2
1.8.0_66 30 2015 年 10 月 8
1.8.0_71 7 2016 年 1 月 1
1.8.0_72 4 2016 年 2 月 1
1.8.0_73 131 2016 年 3 月 2
1.8.0_77 2 2016 年 3 月 10
1.8.0_91 137 2016 年 4 月 9
1.8.0_92 441 2016 年 5 月 14
表 3:版本和 CVE

* 补丁更新 8u92 中发现的得分高于 9 (9.3) 的 CVE 列表:CVE-2016-3610CVE-2016-3598CVE-2016-358710。PSU 8u102 或 CPU 8u101 已修补这些严重漏洞。 

有关 CVE 的更多信息,请访问:https://docs.azul.com/core/cve 

OpenJDKOracle Oracle JDK Oracle Corporation 的财产。

简化 Java 迁移

OpenJDK 是关键。访问 Azul 迁移学习中心。