Java包管理以及Maven包管理

众所周知,Java包管理是学习Java过程中一个很重要的内容。本篇文章将着重介绍Java包管理以及Maven包管理的原理,以及解决包冲突的方法。

JVM工作原理

首先,我们先来了解一下JVM的工作原理,其实简单地概括性地说,JVM只会做两件事情:

  1. 执行一个类的字节码
  2. 在执行这个类的字节码的时候,若碰到了新的类,则加载它
  3. 不断重复以上两个过程

可见,JVM的工作是如此的简单和枯燥,但读到这里的你,可能会产生一个问题,JVM是怎么知道在哪里读取这些类的呢?
针对这个问题,我也不卖关子了,直接告诉你答案,JVM是通过classpath参数来获取到这个路径的。
那么新的问题又出现了,我明明没有给JVM传递这个参数呀,它是怎么获取到的呢?

是的,没错,你没有给JVM传递classpath这个参数,但是你的编译器偷偷帮你干了这件事情了!

(不相信的话,每次用编译器编译的时候,控制台都会有一串命令,在命令里面你可以清楚地看到编译器给JVM偷偷传递了classpath参数)

给JVM传递classpath参数
给JVM传递classpath参数

另外,由于一个包有可能又依赖于其他很多个包,因此一个项目下来,可能classpath下的依赖路径会变得又臭又长。
在Java刚诞生的时候,人们是需要通过手写这些classpath路径来让JVM读懂读取jar包(一堆类的集合)的路径的,后面再人们的不断努力下,强大的IDEA和Maven的诞生,才让这个繁琐的过程变得无比简单。

依赖地狱

在Maven诞生之前,依赖冲突是一个很容易发生且很难解决的问题,我们把这种依赖冲突又称为classpath hell(依赖地狱)。
什么是依赖冲突,由于全限定类名是类的唯一标示,因此当多个同名类不同版本同时出现在classpath的时候,就是噩梦的开始。

依赖冲突
依赖冲突

如上图,A包依赖了B包和C2包,而B包又依赖了C1包,在这个时候,由于所有的依赖包的路径都会写在classpath上面,让JVM从前往后地在这些路径上面寻早需要的依赖包,因此,若JVM先读取到了C1依赖包的classpath路径,那么C2这个依赖包,由于和C1只是版本上面的不同,因此JVM会误把C1路径中找到的依赖包也同样作用在C2上面,从而导致出现不可预期的错误。

一般来说,当你看到你的代码在编译运行之后,出现了以下的错误,那就代表最麻烦的包冲突出现了:

  1. AbstractMethodError
  2. NoClassDefFoundError
  3. ClassNotFoundException
  4. LinkageError

Maven包管理的原理

在Maven没有诞生之前,包冲突只能通过手动寻找冲突的包依赖,并把对应的包进行升级或者替换,但问题是,一个项目一般存在着很多很多的包依赖,手动寻找费时费力,效率太低。直到后来Maven的诞生,才使得解决包依赖的解决变得不再那么麻烦。

首先我们先来了解一下Maven是如何对包进行管理的
我们需要首先知道的是,Maven有一套约定俗成的规范,其中规定了,生产代码需要放在src/main目录下面,而测试代码则需要放在test/main目录下面。这个将在之后讲包管理的scope中有用。

Maven会有中央仓库和本地仓库两个仓库
本地仓库即字面意思在本地你电脑中存在的仓库,它默认位于~/.m2目录中,里面会放置一些经过下载的第三方包的缓存。
而中央仓库即线上仓库的意思,一个包会含有groupIdartifactIdversion三个字段,因此在中央仓库中,一个包存放的路径也是以这三个字段来存放的,具体会存放在groupId/artifactId/version这个位置。

当一个项目需要使用一些第三方包的时候,你可以在pom文件中添加这些包的信息,这样Maven就会自动帮你下载这些包以及其相关依赖包到本地中缓存起来,具体的添加方式如下图所示:

pom文件
pom文件


如何解决包冲突

好了,说到这里,相信你已经基本了解了Maven是如何对第三方包进行管理的了,接下来,我们就来讲一下Maven是如何解决包冲突的。
首先我们需要知道解决包冲突的一个原则:绝对不允许最终的classpath出现同名不同版本的jar包

在Maven中,当出现包冲突的问题的时候,Maven会保留离项目最近的包,而去除其他有冲突的包,拿之前的例子来说:
解决依赖冲突
解决依赖冲突

相比于C1来说,C2这个第三方包离项目更接近,因此Maven会自动帮你把C1去除,而保留C2。但是这种策略有时候是不完美的,因此有时候也需要我们人为地去维护它,但不管怎么说,由于Maven的诞生,使得我们对于第三方包的很多操作都变得轻松和简单了。

接下来我们来说一下人为解决冲突的三种办法:

  1. 直接依赖高版本依赖,这样Maven就能去除所有低版本的不合适的依赖了,具体来说如下所示:
解决依赖冲突
解决依赖冲突

C1、C2和C3三个版本冲突了,但我们只要直接依赖了最高版本C3,把它作为项目的直接依赖,这样C1、C2这两个不合适的第三方包就会自动被Maven去除掉,从而解决了冲突。

  1. 通过pom文件来排除包中的后代指定依赖

具体操作如以下代码所示:

<dependency>
  <groupId>xxx</groupId>
  <artifactId>xxx</artifactId>
  <version>1.0.0</version>
  <exclusions>
    <exclusion>
        <groupId>yyy</groupId>
      <artifactId>yyy</artifactId>
    </exclusion>
  </exclusions>
</dependency>

通过以上的代码,即可排除了xxx依赖中的后代yyy依赖,也可以解决包冲突的问题

3.通过Maven helper插件来解决包冲突问题,由于这个是工具性的操作,因此这里不过多介绍,大家可以自行去尝试。

最后,说一下pom文件中,可以通过设置scope标签,来指定一个包是否可以被生产代码和测试代码所引用:

  1. complie(生产代码以及测试代码均可见)
  2. test(只有测试代码可见)
  3. provided(只在编译的生产代码的时候生效,在运行时无效)

以上,就是本篇文章的所有内容,谢谢阅读~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342