base64是哪个jar包的_Java包管理的那些事3——包

前情回顾:

Java包管理的那些事1——IDE背后发生了什么

Java包管理的那些事2——神奇字节码在哪里

包就是一堆字节码文件的集合

我们在前两回中讲到,JVM的设计相当简单粗暴:

  1. JVM按照类的全限定类名,去Classpath所指定的目录中挨个查找字节码文件;
  2. 找到之后,就阅读这份说明书(类的字节码),按照要求工作:每个说明书都写了自己的用法用量,饭前还是饭后服用;
  3. 如果这份说明书中提到了其他类的全限定类名,则重复步骤1的操作。

在这个过程中,Classpath从哪儿来,里面包含些什么东西,傲娇的JVM完全不关心:我只要能在你给的Classpath里找到说明书就行,其他的我不管。

那么问题来了,假如你要使用第三方库,你要如何找到这些说明书?

或者换个问题,你怎么把你自己写的说明书给全世界人民使用?

很容易想到,你需要把你自己写的一叠说明书(你的库不大可能只包含一个类对吧)装订好,放在一个地方,任人观看和复制。任何一个JVM捡起来这叠说明书,就能毫不费力的理解并执行你写的逻辑。

我们称这样的一叠说明书为:包

7f60cf34a702ef783418157dc83c1540.png

重复一遍:

把你自己写的一叠说明书(包)装订好(打包),放在一个地方(个人网站或者包仓库),任人观看和复制(下载)。

反映到现实世界中,就是你要用哪个包,就从什么地方下载或者复制一个jar包,然后告诉傲娇的JVM(放到Classpath中)。

这就是Java的包系统的基石。

包的依赖和传递性依赖

听上去似乎很简单。你要用哪个类,就把包含它的jar包下载下来,然后放到JVM的Classpath里。举个栗子:

98e478a949303f47de6e22870b4c7688.png

你要使用一个类org.junit.Assert。你知道这是JUnit 4的一部分,于是你兴冲冲地打开了官网,下载了junit-4.12.jar,然后放到Classpath里,启动JVM。JVM也兴冲冲地打开了org.junit.Assert类的说明书(字节码),然后大声的抱怨:

NoClassDefFoundError: org.hamcrest.Matcher

你定睛一看,org.junit.Assert的说明书在这里提到了一个另外的一个类,org.hamcrest.Matcher,但是却没有包含在 junit-4.12.jar里。

发现问题在哪里了么?通常情况下,你发布的这一叠说明书只包含你自己的类——你在写代码的时候引用的类都变成了一个全限定类名,印在说明书里了,这些类的说明书却没有随你的包一起发布。

我们称这种引用关系为包的依赖。换句话说,A包依赖了B包,那么意味着JVM在只有A包的时候是无法运行的。

你说,好办,那我就把B包也下载下来放到Classpath中不就行了?

JVM十分感动,然后十分悲痛地告诉你,B包的类引用了C包的类。C包依赖了D包和E包……

我们称这种关系为传递性依赖

传递性依赖带来的问题

我们假设你是一个非常坚强的人,把所有的传递性依赖都找到后拼装了一个完整的Classpath给JVM。JVM很开心。

而你不一定开心。因为你数了数你的Classpath,包含了一千个包。

一千个包,放在记事本里黑压压的一大片,想想都觉得觉得刺激。

更刺激的是,你需要维护它。随着项目的规模增长,你需要引用一个额外的包X。你检查了包X,发现它依赖Y和Z。 Y包已经在你的Classpath里了,因此跳过它。Z包不在你的Classpath里,于是你把它添加进来。现在你开始检查Z包的依赖了……

更更刺激的是,假如你在这个过程中犯了一个错误,遗漏了某些包,JVM可能不会立刻崩溃——因为它只有运行到某个类找不到时才会大声抱怨。它可能平稳地运行了几天几个月都没运行到会出错的代码那里。突然,在情人节的晚上你和你的女票你侬我侬的时候,Boom!老板的夺命连环call过来了。

更更更刺激的是,你犯的错误可能不是遗漏了某些包,而是在Classpath中某些包重复了。我们前两节讲过,JVM在按照全限定类名查找一个类的时候,会挨个检查Classpath中的字节码目录(jar包),先找到哪个就用哪个。碰巧,你的Classpath中包含同一个库的不同版本(你一摊手,我的Classpath里有一千个包,犯个错误不是很正常么!),并且有Bug的版本更靠前。

最刺激的是,以上这些问题可能同时、随机发生……

咋办?在Java问世的前十年,业界一直在探索这些问题的解决方案。

欲知后事如何,且听下回分解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值