杰尔·地狱

什么是JAR地狱? (或者是classpath地狱?还是依赖地狱?)在考虑使用Maven或OSGi等现代开发工具时,哪些方面仍然有意义?

有趣的是,似乎没有对这些问题的结构化答案(即,即使第二页也没有希望的头条新闻)。 该职位应填补这一空白。

总览

我们将从构成JAR地狱的一系列问题开始,暂时忽略构建工具和组件系统。 当我们评估当前的状况时,我们将回到第二部分。

杰尔·地狱

JAR Hell是一个可爱的术语,指的是Java的类加载机制的特性所引起的问题。 其中一些相互依存。 其他人是独立的。

未表达的依赖性

JAR无法以JVM可以理解的方式来表示它依赖的其他JAR。 需要一个外部实体来识别和实现依赖关系。 开发人员必须通过阅读文档,找到正确的项目,下载JAR并将其添加到项目中来手动执行此操作。 可选的依赖项(如果开发人员要使用某些功能,则JAR可能仅需要另一个JAR)会使过程进一步复杂化。

运行时在需要访问依赖之前,将不会检测到它们。 这将导致NoClassDefFoundError崩溃正在运行的应用程序。

传递依存关系

为了使应用程序正常工作,可能只需要少数几个库。 每个反过来可能需要少量其他库,依此类推。 由于未表达的依赖关系的问题变得更加复杂,因此它变得越来越费力且容易出错。

遮蔽

有时,类路径上的不同JAR包含具有相同完全限定名称的类。 可能由于不同的原因而发生这种情况,例如,当同一库有两个不同版本时,或者当胖JAR包含也作为独立JAR引入的依赖项时,或者当一个库被重命名并在不知不觉中两次添加到类路径时。

因为将从类路径上的第一个JAR加载类以包含它们,所以该变体将“遮盖”所有其他类并使它们不可用。

如果变体在语义上有所不同,则可能导致从微妙到通知错误的行为到破坏破坏性错误的一切。 更糟糕的是,此问题本身表现出来的形式似乎不确定。 这取决于搜索JAR的顺序。 这在不同的环境中可能完全不同,例如在开发人员的IDE和最终将运行代码的生产机器之间。

版本冲突

当两个必需的库依赖于第三个库的不同的,不兼容的版本时,就会出现此问题。

如果两个版本都存在于类路径中,则该行为将不可预测。 首先,由于存在阴影,两个版本中都存在的类将仅从其中一个加载。 更糟糕的是,如果访问一个中存在但另一个不存在的类,则该类也将被加载。 因此,调用库的代码可能会同时找到这两个版本。

由于需要不兼容的版本,如果缺少其中一个版本,则该程序很可能无法正确运行。 同样,这可以表现为意外行为或NoClassDefFoundErrors。

复杂类加载

默认情况下,所有应用程序类均由同一类加载器加载,但是开发人员可以自由添加其他类加载器。

这通常是通过组件系统和Web服务器之类的容器完成的。 理想情况下,这种隐式使用对应用程序开发人员是完全隐藏的,但是,众所周知, 所有抽象都是泄漏的 。 在某些情况下,开发人员可能会明确添加类加载器以实现功能,例如,允许其用户通过加载新类来扩展应用程序,或者能够使用具有相同依赖性的冲突版本。

无论多个类加载器如何进入画面,它们都可以Swift导致显示出意料之外且难以理解的行为的复杂机制。

类路径地狱和依赖地狱

Classpath地狱和JAR地狱本质上是同一件事,尽管后者似乎更加关注由复杂的类加载器层次结构引起的问题。 这两个术语都特定于Java和JVM。

另一方面, 依赖地狱是一个使用更广泛的术语。 它描述了软件包及其依赖项的一般问题,适用于操作系统以及各个开发生态系统。 考虑到它的通用性,它并不涵盖特定于单个系统的问题。

从上面的列表中,它包括可传递的和可能未表达的依赖关系以及版本冲突。 类的加载和屏蔽是Java特定的机制,依赖地狱将不会涵盖这些机制。

由惠康图书馆根据CC-BY 4.0发布

发布时间由惠康图书馆在CC-BY 4.0

事态

构建工具

查看问题列表,我们看到构建工具如何帮助解决其中的一些问题。 它们擅长使依赖关系显式化,以便可以沿着传递依赖关系树的无数边沿搜寻每个所需的JAR。 这在很大程度上解决了未表达和传递依赖的问题。

但是Maven等。 对阴影不做任何事情。 尽管它们通常致力于减少重复的类, 但不能阻止它们 。 除了指出版本冲突之外,构建工具也无助于解决版本冲突。 而且由于类加载是运行时构造,因此它们也不涉及。

组件系统

我从未使用过OSGi或Wildfly之类的组件系统,因此无法证明它们的工作情况。 从他们的说法看来,他们似乎能够解决大多数JAR地狱问题。

但是,这带来了额外的复杂性,并且经常要求开发人员更深入地研究类加载器机制。 具有讽刺意味的是,上面的列表中也有一点。

但是,无论组件系统是否确实在很大程度上缓解了JAR地狱的痛苦,我的印象是,绝大多数项目都没有使用它们。 在这种假设下,绝大多数人仍然遭受与类路径有关的问题。

这在哪里离开我们?

由于它们未被广泛使用,因此组件系统不会影响大局。 但是,构建工具的普遍存在大大改变了JAR地狱不同圈子的严重性。

我参与或听说过的任何构建工具都不支持的项目都花费了大量的时间来处理来自未表达或可传递依赖的问题。 阴影有时会抬起丑陋的头,需要花费不同的时间来解决-但最终总是如此。

版本冲突是JAR地狱中最棘手的问题。

但是,每个项目迟早都要依靠相互冲突的版本进行斗争,并且必须做出一些艰难的决定才能解决这些问题。 通常,必须推迟某些所需的更新,因为这将强制执行当前无法执行的其他更新。

我敢说,对于大多数大小合适的应用程序,服务和库,版本冲突是何时以及如何更新依赖项的主要决定因素之一。 我觉得这是无法忍受的。

对于非平凡的类加载器层次结构,我经验不足,无法评估它们有多少重复出现的问题。 但是考虑到我迄今为止从事的所有项目都不需要它们,我敢说它们并不常见。 在网络上搜索使用它们的原因通常会发现我们已经讨论的内容:依赖关系导致版本冲突。

因此,根据我的经验,我会说版本冲突是JAR地狱中最棘手的问题。

反射

我们已经讨论了JAR地狱的构成要素:

  • 未表达的依赖性
  • 传递依赖
  • 遮蔽
  • 版本冲突
  • 复杂类加载

根据为游戏带来的构建工具和组件系统以及它们的使用范围,我们得出结论,很大程度上解决了未表达的和可传递的依赖关系,这至少掩盖了缓解和复杂类加载的不常见性。

这使版本冲突成为JAR地狱中最有问题的方面,影响了大多数项目中的日常更新决策。

翻译自: https://www.javacodegeeks.com/2015/10/jar-hell.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/356748.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab实验符号计算答案,实验五matlab符号计算

实验五matlab符号计算 实验 5 符号计算 教师评分班级 学号 姓名实验日期 2014 年 6 月 17 日 星期 二 第 1 至 2 节课实验地点实验目的1. 掌握定义符号对象的办法2. 掌握符号表达式的运算法则以及符号矩阵运算3. 掌握求符号函数极限及导数的方法4. 掌握求符号函数定积分和不定积…

Java学习笔记之:Java String类

一、引言 字符串广泛应用在Java编程中,在Java中字符串属于对象,Java提供了String类来创建和操作字符串。 创建字符串最简单的方式如下: String str "Hello world!"; String类型是特殊的引用类型,我们也可以通过实例化的方式来创建 …

WildFly 10 CR 2发布– Java EE 7,Java 8,Hibernate 5,JavaScript支持热重载

昨天,WildFly团队发布了最新版本的WildFly 10 。 CR2很可能是预计于十月份发布最终版本之前的最后一个版本。 即使主要支持的Java EE规范是7,WildFly 8和WildFly 9仍具有许多新功能,该版本现在具有三个服务器版本,实现了Java EE 7…

openshift 部署_OpenShift Express:部署Java EE应用程序(支持AS7)

openshift 部署在过去的几年中,我越来越多地听说过“云”服务。 最初,我并不是很想尝试一下。 但是几个月后(一年?),我决定看看这是怎么回事。 我从事Java EE开发已有7年以上,因此,我…

迪克逊准则matlab,浙江科技学院学报

引言传统的农业栽培需要遵循季节性及周期性的栽培规律,受外界环境的影响较大,相应的栽培技术无法得到良好的栽培结果[1]。而温室大棚通过环境控制器调节温室环境,为作物提供了合适的生长环境。因此,它在农业领域的应用越来越广泛,温室环境控制系统的研究成为人们关注的热点[2-5…

使用FlexDeploy对融合中间件应用程序进行自动化软件测试

自动化软件测试是任何软件组织都应执行的强制性活动之一,以保证其产品质量。 但是,此过程通常变得非常复杂,尤其是涉及由多个不同部分组成的现代复杂系统的自动化测试时。 所有这些部分都基于不同的技术,显然,应该使用…

java 反编译项目_Java 7 –反编译项目硬币

java 反编译项目大家好,该是从2012年开始写作的时候了。正如您在其他博客中可能已经看到的那样,有一些更改可以使您使用Java编程时的开发人员生活变得更加轻松:Diamond运算符,Switchs中的Strings,尝试使用资源&#xf…

Java 9代码工具:使用Java微型基准测试工具的实践会话

用肉眼看,基准测试似乎只是确定执行某些代码需要花费多长时间的简单问题。 但是通常,这是幼稚的方法。 提供具有准确和可重复结果的有意义的基准并非易事。 在本文中,我们想向您介绍OpenJDK代码工具项目,尤其是JMH。 Java Microb…

vaadin_在Vaadin和JSF之间选择

vaadin随着最新版本的Primefaces 3.0的发布,JSF终于达到了前所未有的成熟度和实用性,使其与其他流行的Rich Internet Applications(RIA)选项面对面,例如Google Web Toolkit(GWT),Ext…

windows server 2008 oracle 10g,一次不太愉快的Windows Server 2008 R2 SP1上安装ORACLE 10G经历...

华为服务器型号RH5885 V3,安装windows server 2008 r2, oracle 10g1、安装包要使用10204_vista_w2k8_x64_production_db.zip,不用102010_win64_x64_database.zip;2、DBCA创建数据库之前,关闭BIOS中Hyper-Threading [ALL] - [Disab…

通过OmniFaces缓存组件以编程方式缓存PrimeFaces图表

在这篇文章中&#xff0c;您将看到如何结合PrimeFaces和OmniFaces获得可缓存的图表。 为了使事情变得简单&#xff0c;我们将使用PrimeFaces 折线图。 对于这种图表&#xff0c;我们可以在页面中使用<p&#xff1a;chart />标记和一个简单的托管bean。 因此&#xff0c;在…

ReactNative——打包发布

1、生成一个签名密钥 ‘ keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000 ’ 生成一个my-release-key.keystore的密钥库文件 2、找到路径/android/app/src/main,并在该目录下新建assets文件夹 3、在工程…

oracle版本说明,Oracle版本说明

Oracle 的版本号很多&#xff0c;先看11g的一个版本号说明&#xff1a; 注意&#xff1a; 在Oracle 9.2 版本之后&#xff0c; oracle 的maintenance release number 是在Oracle的版本号很多&#xff0c;先看11g的一个版本号说明&#xff1a;注意&#xff1a;在Oracle 9.2版本之…

Opserver配置Redis、SqlServer监控

简介 Opserver是Stack Overflow的开源监控解决方案&#xff0c;由Stack Exchange发布&#xff0c;基于.NET框架构建。开源地址&#xff1a;https://github.com/opserver/Opserver 使用 github下载源代码编译后&#xff0c;发布至IIS&#xff0c;需要先修改Opserver/Config目录下…

Linux挂载多个文件夹读不出,FTP不显示Linux挂载文件夹怎么办?-处理FTP不显示Linux挂载文件夹的方案 - 河东软件园...

最近有位用户向小编反映&#xff0c;声称自己在Linux中使用vsftpd启FTP服务&#xff0c;并在FTP用户下挂载一个Windows的共享盘&#xff0c;但是登陆FTP后却无法显示该挂载的共享盘。出现这种问题真是令人十分头疼呢&#xff0c;想要快速解决这个问题又找不到合适的方法。该怎么…

以太坊智能合约Hello World示例程序

简介 以太坊(Ethereum)是一提供个智能合约(smart contract)功能的公共区块链(BlockChain)平台. 本文介绍了一个简单的以太坊智能合约的开发过程. 开发环境 在以太坊上开发应用&#xff0c;首先需要安装其客户端&#xff0c;本文使用基于Go语言的Geth, 其官网为https://github.c…

Java到LDAP教程(包括如何安装LDAP服务器/客户端)

本教程将向您展示如何编写Java代码以与LDAP交互。 但是在执行此操作之前&#xff0c;我们需要在计算机上设置LDAP服务器和客户端。 如果此时您不确定到底是什么LDAP&#xff0c;建议您参考这篇文章&#xff0c;其中提供了一个很好的定义示例。 &#xff08;简而言之&#xff0…

在linux下赋予000权限,【linux】对于文件权限的理解

本篇博文旨在介绍linux下的权限问题&#xff1b;介绍了Linux下&#xff0c;查看权限、修改权限等方法&#xff1b;并通过分别在超级用户(root)和普通用户下进行测试&#xff0c;探索不同等级的用户进入目录需要的权限&#xff0c;以及进入后&#xff0c;显示和创建文件需要的权…

手把手教你制作简易计算器

实现过程&#xff1a; HTMLCssJS 具体通过标签实现计算器整个的框架 通过Css样式实现计算器页面布局及框架优化 通过JavaScript算法实现计算器计算过程 次实验过程&#xff1a; 背景图片背景音乐&#xff08;看个人意愿加&#xff01;&#xff09; 安排&#xff1a; <!--HT…

安装tron_具有Tron效果的JavaFX 2 Form

安装tron这是一个具有TRON效果的简单JavaFX登录表单。 在此示例中&#xff0c;我使用CSS设置TextField和Button的样式。 这是CSS和Effect代码的片段&#xff1a; .text-field{-fx-background-color: transparent;-fx-border-color: #00CCFF;-fx-text-fill: white; }.password-f…