写代码啦
java包管理和maven初步
回复数(0) 浏览数(114)
{{topic.upvote_count || 0}} 编辑 回复

闲言

每次说到JVM的时候不自觉的想到小时候,很多玩的游戏的安装程序会变成虚拟光碟再进行安装,一些网游单机化也是要虚拟机支持,比如洛奇英雄传。那么JVM是怎么扮演好JAVA虚拟机的角色的,简单分享下我所学。

JVM运行代码

编译:将源代码变为字节码
运行:JVM加载字节码开始运行
JVM在开始运行class字节码后,难免涉及新的class,那么其就会进入新class中继续从头开始,周而复始直到运行结束。
如果说一开始的run按钮是我按下的,class的位置是我给JVM的,后面新的类的是如何找到并加载的呢?

包管理

类路径(classpath)

类路径可以用-classpath查看,windows中不同path之间用;(分号)隔开。
com.github.hcsp.encapsulation这个的路径可以找到是D:\JAVA\IdeaProjects\factory-method-pattern\target\classes
那么它的具体路径就是两个合并到一起:
D:\JAVA\IdeaProjects\factory-method-pattern\target\classes\com\github\hcsp\encapsulation.class
三方包也可以在cp中找到,在MAVEN刷新或者mvn命令时会自动下载到本地,默认文件夹是.m2
而把多个class压缩在一起就是jar包,可以使用解压缩查看其中的class文件。

classpath hell

在pom.xml文件中可以找到依赖的包123等,包123本身可能分别依赖包ab,cd,ef等,这样会带来两个结果。
1. 包的依赖具有传递性,依赖关系会形成依赖树
2. classpath会特别长,因为要把所有被依赖的包的cp添加进去


问题来了,假如cp中有两个或这多个不同版本同名的jar包,里面很可能有两个同名类这种情况下加载哪个类?
答案是谁在前,加载谁。这就可能导致使用的class并不是你想要用的版本,造成运行的隐患。

包管理历史

包管理本质就是告诉JVM如何找到所需的第三方类库以及如何解决其中的冲突问题。
* 最早期时候手动写命令行编译添加jar包;
* Apache ant之后可以通过配置完成包的管理,但是问题也很突出:
1. 每个人都有不同的标准,代码复用性差;
2. 手动下载jar包,若成百上千就要挨个去官网找最新版本,破坏心智;
3. 没有解决 classpath hell问题
* Maven本身不止包管理的功能,还有自动化构建等功能。
它的出现使包管理变得顺畅且无痛,原因在于
Convention over configuration 约定优于配置

maven之于包管理

maven本身的中央仓库在远端的服务器上,其中存储着几乎所有的包,本地包会在依赖后mvn时下载到本地仓库,默认是~/.m2。
maven为所有的包进行编码,赋予Groupld/artifactld/version三个属性,分别对应路径,名称,版本号。使类的全限定类名(目录层级)为唯一确定的类。
现在就很好理解当你在本地pom中添加三方jar包刷新的时候,会从远程仓库下载jar包,校检完整工具,以及其依赖的包的pom文件,根据传递性依赖下载成依赖树jar包。

解决包冲突

常见的包冲突的报错类型:

AbstractMethodError
NoClassDefFoundError
ClassNotFoundError
LinkageError

传递性依赖的自动管理原则:
1. 绝对不允许最终的 cp中存在同名不同版本的jar包;
2. 同名优先使用最近的,同距离的同名优先使用靠前的

解决思路有三各方面:
1. 强行直接依赖所要的类库,使其最近被依赖;
2. 排除不用的jar包;
3. 在IDEA中安装使用dependency helper插件;

作用域scpoe

Compile: 在main和test中都有效果;
Test: 只在test包中使用;
Provided:只在编译main有效,运行时无效;
Provided存在的意义在于你的程序可能会在编译后装在compile容器中,而容器本身就提供了一些jar包,如果本身也有依赖的话,会产生包冲突。

{{topic.upvote_count || 0}}

闲言

每次说到JVM的时候不自觉的想到小时候,很多玩的游戏的安装程序会变成虚拟光碟再进行安装,一些网游单机化也是要虚拟机支持,比如洛奇英雄传。那么JVM是怎么扮演好JAVA虚拟机的角色的,简单分享下我所学。

JVM运行代码

编译:将源代码变为字节码
运行:JVM加载字节码开始运行
JVM在开始运行class字节码后,难免涉及新的class,那么其就会进入新class中继续从头开始,周而复始直到运行结束。
如果说一开始的run按钮是我按下的,class的位置是我给JVM的,后面新的类的是如何找到并加载的呢?

包管理

类路径(classpath)

类路径可以用-classpath查看,windows中不同path之间用;(分号)隔开。
com.github.hcsp.encapsulation这个的路径可以找到是D:\JAVA\IdeaProjects\factory-method-pattern\target\classes
那么它的具体路径就是两个合并到一起:
D:\JAVA\IdeaProjects\factory-method-pattern\target\classes\com\github\hcsp\encapsulation.class
三方包也可以在cp中找到,在MAVEN刷新或者mvn命令时会自动下载到本地,默认文件夹是.m2
而把多个class压缩在一起就是jar包,可以使用解压缩查看其中的class文件。

classpath hell

在pom.xml文件中可以找到依赖的包123等,包123本身可能分别依赖包ab,cd,ef等,这样会带来两个结果。
1. 包的依赖具有传递性,依赖关系会形成依赖树
2. classpath会特别长,因为要把所有被依赖的包的cp添加进去


问题来了,假如cp中有两个或这多个不同版本同名的jar包,里面很可能有两个同名类这种情况下加载哪个类?
答案是谁在前,加载谁。这就可能导致使用的class并不是你想要用的版本,造成运行的隐患。

包管理历史

包管理本质就是告诉JVM如何找到所需的第三方类库以及如何解决其中的冲突问题。
* 最早期时候手动写命令行编译添加jar包;
* Apache ant之后可以通过配置完成包的管理,但是问题也很突出:
1. 每个人都有不同的标准,代码复用性差;
2. 手动下载jar包,若成百上千就要挨个去官网找最新版本,破坏心智;
3. 没有解决 classpath hell问题
* Maven本身不止包管理的功能,还有自动化构建等功能。
它的出现使包管理变得顺畅且无痛,原因在于
Convention over configuration 约定优于配置

maven之于包管理

maven本身的中央仓库在远端的服务器上,其中存储着几乎所有的包,本地包会在依赖后mvn时下载到本地仓库,默认是~/.m2。
maven为所有的包进行编码,赋予Groupld/artifactld/version三个属性,分别对应路径,名称,版本号。使类的全限定类名(目录层级)为唯一确定的类。
现在就很好理解当你在本地pom中添加三方jar包刷新的时候,会从远程仓库下载jar包,校检完整工具,以及其依赖的包的pom文件,根据传递性依赖下载成依赖树jar包。

解决包冲突

常见的包冲突的报错类型:

AbstractMethodError
NoClassDefFoundError
ClassNotFoundError
LinkageError

传递性依赖的自动管理原则:
1. 绝对不允许最终的 cp中存在同名不同版本的jar包;
2. 同名优先使用最近的,同距离的同名优先使用靠前的

解决思路有三各方面:
1. 强行直接依赖所要的类库,使其最近被依赖;
2. 排除不用的jar包;
3. 在IDEA中安装使用dependency helper插件;

作用域scpoe

Compile: 在main和test中都有效果;
Test: 只在test包中使用;
Provided:只在编译main有效,运行时无效;
Provided存在的意义在于你的程序可能会在编译后装在compile容器中,而容器本身就提供了一些jar包,如果本身也有依赖的话,会产生包冲突。

114
回复 编辑