侬娜·杰尔_杰尔·地狱

侬娜·杰尔

什么是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/336900.shtml

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

相关文章

cmake 安装mysql5.6_CMAKE安装MYSQL 5.6.10

mysql5.6.10不支持configure安装了,提供了CMAKE安装方式 #sudo groupadd mysql #sudo useradd mysql -g mysql #sudo mkdir -p /home/mysql/data #sudo mkdir /usr/local/mysql #sudo mkdir /var/log/mysql #sudo chown -R mysql:mysql /home/mysql/data #sudo cho…

java 多线程变量可见性_Java多线程:易变变量,事前关联和内存一致性

java 多线程变量可见性什么是volatile变量? volatile是Java中的关键字。 您不能将其用作变量或方法名称。 期。 我们什么时候应该使用它? 哈哈,对不起,没办法。 当我们在多线程环境中与多个线程共享变量时,通常使用v…

Mysql运行在内核空间_思考mysql内核之初级系列6—innodb文件管理 | 学步园

在上一篇里面,bingxi和alex思考了information_schema,这个一直在innodb外围打转。没有进入到innodb的内部。在后续的文章中,以innodb的为主,逐个思考。Bingxi和alex今天了解了fil文件管理。对应的文件为:D:/mysql-5.1.…

pcl_openmap_OpenMap教程第2部分–使用MapHandler构建基本地图应用程序–第1部分

pcl_openmap1.简介 在第一个教程中,我们创建了一个基本的OpenMap GIS应用程序,该应用程序在JFrame中显示一个从文件系统加载的具有一个形状图层的地图。 该教程基于com.bbn.openmap.app.example.SimpleMap 。 在该教程中,我们使用了以下OpenM…

mysql7.5安装教程_CentOS7.5下yum安装MySQL8图文教程

卸载MariaDB1.列出所有安装的MariaDB rpm 包rpm -qa | grep mariadb2.强制卸载rpm -e --nodeps mariadb-libs-5.5.60-1.el7_5.x86_64安装MySQL1. 环境CentOS7.52. 获取MySQL最新版 rpm包yum仓库下载MySQLyum localinstall https://repo.mysql.com//mysql80-community-release-e…

字符串url获取参数_如何从URL查询字符串获取示例参数或将其附加到URL查询字符串(示例)?...

字符串url获取参数让我们剖析几个简单的用例,并查看视图参数的工作原理(视图参数名称不是强制性的,以匹配通过URL查询字符串传递的请求参数,但在本文中,我们将重点讨论这种情况): 情况1 在inde…

mysql和sqlserver分页的区别_关于SQLServer和MySQL 查询分页语句区别

首先来定义几个要用到的参数(例子)t_user数据表int currentPage ; //当前页int pageRecord ; //每页显示记录数关于SqlServer数据库分页SQL语句为:String sql "select top "pageRecord " * from t_user where id not in (select top "(currentPage-1)*pag…

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

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

mysql快速随机_MySQL随机取数据最高效的方法

mysql随机取数据最高效率的方法发现在SQL语句里有一个 ORDER BY rand() 这样的一个语句,这个说是用着方便,但是效率实在是太低了,于是我用了以下的方法来优化,就是用JOIN表的方法来达到这个取随机数据行的方法,你可以用…

部署被测软件应用和中间件_使用FlexDeploy对融合中间件应用程序进行自动化软件测试...

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

python batch_size_python 實現動態 batch size,多張圖片如何堆疊轉成指針

前陣子有發問,關於 python 動態 batch size 如何實現,目前解決之前問題現在遇到的問題是當我把兩張圖片直接用 numpy concat 堆疊在一起 進行 acl.util.numpy_to_ptr 轉換成指針進行推理後,得到的結果只有第一張圖片是對的,第二張…

投行数据_投行对Java的二十大核心访谈问答

投行数据这是在金融领域(主要是在大型投资银行)共享Java核心访谈问题和答案的新系列。 在JP Morgan,Morgan Stanley,Barclays或Goldman Sachs上会问许多这些Java面试问题。 银行主要从多线程 , 集合 ,序列化…

php中mysql_fetch_row_php中的mysql_fetch_row,mysql_fetch_array,mysql_fetch_object

1.mysql_fetch_rowmysql_fetch_row,这个函数是从结果集中取一行作为枚举数据,从和指定的结果标识关联的结果集中取得一行数据并作为数组返回。每个结果的列储存在一个数组的单元中,偏移量从 0 开始。 注意,这里是从0开始偏移&…

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

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

mysql开发问题解决_开发过程中mysql常见问题的解决方法

本篇文章给大家带来的内容是关于开发过程中mysql常见问题的解决方法&#xff0c;有一定的参考价值&#xff0c;有需要的朋友可以参考一下&#xff0c;希望对你有所帮助。记录开发过程中遇到mysql相关的问题以及解决方法&#xff0c;长期更新。远程连接问题mysql默认连接只能给本…

javaone_JavaOne 2015继续进行,Java将永远存在(……也许是长篇大论)

javaone好的。 也许我的标题太夸张了。 我确实相信Java&#xff0c;生态系统&#xff0c;社区&#xff0c;虚拟机和母编程语言将会存在很长一段时间。 有什么可以偏离的&#xff1f; 假定在我的酒店房间中花费很多时间&#xff0c;在我的演讲中增加技巧之间&#xff0c;我认为…

hmailserver mysql密码_第二步:点晴MIS系统Email模块hMailServer数据库连接配置指引

点击&#xff1a;windows系统-》开始-》所有程序-》hmailserver-》hMailServer Database Setup&#xff0c;在弹出的对话框中输入默认管理密码“clicksun2010”&#xff0c;进入后按照以下步骤操作&#xff1a;输入登陆密码&#xff1a;clicksun2010&#xff0c;务必使用这个密…

spring3.0异步_在Spring 4.2中更简单地处理异步事务绑定事件

spring3.0异步介绍 如您可能已经知道的&#xff08;例如&#xff0c;从我以前的博客文章中 &#xff09;&#xff0c;不再需要创建一个单独的类来实现带有onApplicationEvent方法的ApplicationListener &#xff0c;以便能够对应用程序事件做出响应&#xff08;包括来自Spring …

java 插入mysql 日期_Java日期-插入数据库

我需要找出一种将带有java.util.Date字段的记录插入数据库的方法&#xff0c;但我陷入了困境。有谁知道我该怎么做&#xff1f;现在我有类似的东西。java.util.Date myDate new java.util.Date("01/01/2009");sb.append("INSERT INTO USERS");sb.append(&…

jboss fuse 教程_JBoss Fuse –使用MVEL将您的静态配置转换为动态模板

jboss fuse 教程最近&#xff0c;我重新发现了我已经忘记的JBoss Fuse功能&#xff0c;并且我认为其他人可能会从此提醒中受益 。 这篇文章将重点放在JBoss Fuse和Fabric8上&#xff0c;但所有正在寻找最小侵入性方法来为其静态配置文件添加一定程度的动态支持的开发人员也可能…