当前位置: 首页 > news >正文

百度网站建设基本情况东莞排名优化团队

百度网站建设基本情况,东莞排名优化团队,打金传奇rmb回收,灌云网站建设维护背景 最近在在项目中遇到了一个类加载的问题,几经周折没有找到合适的解决方式,只能怪自己学艺不精。没办法只好重拾曾今丢掉的 java 知识,尝试从源头开始分析问题。 环境 Win 10 企业版 java version “1.8.0_251” Java™ SE Runtime Env…

背景

最近在在项目中遇到了一个类加载的问题,几经周折没有找到合适的解决方式,只能怪自己学艺不精。没办法只好重拾曾今丢掉的 java 知识,尝试从源头开始分析问题。

环境

  • Win 10 企业版
    java version “1.8.0_251”
    Java™ SE Runtime Environment (build 1.8.0_251-b08)
    Java HotSpot™ 64-Bit Server VM (build 25.251-b08, mixed mode)

问题描述:

我所遇到的是一个类重复加载的问题,但是这个问题目前并不能完美复现。因此我希望能够通过查看jvm的类加载过程来判断类重复加载的原因,可以在运行时结束一下参数:

java -verbose:class -cp *.jar com.example.Application

但是此时我又遇到问题了,我的 -cp *.jar参数并没有生效。我的初衷是希望能够加载到当前目录下的所有jar包,但是实际情况是并没有加载到。经过多次试验,在这里记录一下我所犯下的错误以及错误的原因。

问题1. java -verbose:class -cp *.jar com.example.Application 加载失败

在这里插入图片描述
可以从图片看到,jvm只是简单的加载了一些启动所需要的类,而我指定的 jar 包一个也没有加载到。从而导致错误 找不到或无法加载主类 com.example.Application ,这是因为在 windows 环境下 *.jar 的通配符并没有生效,正确的通配符的使用方式为:

java -verbose:class -cp * com.example.Application

可以看到,需要移除*.jar中的.jar,只剩下通配符即可。

问题2. java -verbose:class -cp . com.example.Application

-cp .,小朋友,你是否有很多问号,在初学安装配置 java 时,教程里往往会要求你在环境变量下配置一个 CALSSPATH的环境变量,并且要求值为:

.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;  

还小心翼翼的嘱咐你不要忘记加前面的 .,还会告诉你.代表当前目录,不知道有没有思考过JVM到底从当前目录下加载了什么?反正我是没有思考过,总之是在从网上查-cp 测资料时,我在这里碰壁了。
在这里插入图片描述

经过试验,我可以简单的总结为.所代表的是 JVM 会加载当前目录下的文件,但是并不是全部文件,而是相对应的字节码文件。也就是 JVM 会把当前路径作为 classpath,因此会解析当前path下的 class,至于当前 path 下的 jar包嘛,你不指定的话JVM肯定是当做没看见了。

示例

当前我有如下目录

D:\demo01
│  hutool-all-5.4.3.jar
│
└─com└─exampleMain.classMain.java

可以看到 demo01 文件夹下有一个至尊神器 hutool-all 的 jar 包,然后对应有一个 com.example.Main.java java 源码文件,还有一个经过命令编译得到的 com.example.Main.class的 java 字节码文件,编译命令如下:

javac -cp hutool-all-5.4.3.jar com/example/Main.java

对应的com.example.Main.java的源码:

package com.example;
import cn.hutool.core.lang.Console;public class Main{public static void main(String[] args){System.out.println("Hello World");Console.log("hello world by hutool!");}
}

可以看到我在 Main.java中引入了hutool-alljar包中的一个类,当我执行如下命令时:

D:\demo01>java -cp . com.example.Main
Hello World
Exception in thread "main" java.lang.NoClassDefFoundError: cn/hutool/core/lang/Consoleat com.example.Main.main(Main.java:7)
Caused by: java.lang.ClassNotFoundException: cn.hutool.core.lang.Consoleat java.net.URLClassLoader.findClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)... 1 more

可以看到在执行 Console.log("hello world by hutool!") 时发生了找不到类的错误,这是因为在指定 classpath时只指定了当前目录,但没有指定 hutool-all 的 jar 包导致的。在这种情况下 JVM只会读取当前目录下所有对应的编译后的类文件并且执行。

而当我换一种方式指定 classpath 时:

D:\demo01>java -cp * com.example.Main
错误: 找不到或无法加载主类 com.example.Main

可以看到,此时JVM处于找不到我的 com.example.Main.class 类的状态,由此可见 -cp *的命令并没有让 JVM 读取到当前目录下的字节码文件,而且由于没有找到入口类,所以也不清楚JVM是否有加载 hutool-alljar包。

至此,可以看到,我们一次也没有让代码正常执行过。现在,我们退而求其次,先不考虑通配符的问题,而是先尝试让我们的代码跑起来。从上面的代码执行可以看到-cp .可以让JVM读取当前目录下的字节码文件。现在我们只需添加指定一个 hutool-all.jar 即可让我们的代码跑起来。在 windows 下,分隔不同 jar 包的分隔符是 ;

D:\demo01>java -cp .;hutool-all-5.4.3.jar com.example.Main
Hello World
hello world by hutool!

可以看到我们的代码正常执行了。

现在,我们再回过头来试试我们的通配符*

D:\demo01>java -cp ".;*.jar" com.example.Main
Hello World
Exception in thread "main" java.lang.NoClassDefFoundError: cn/hutool/core/lang/Consoleat com.example.Main.main(Main.java:7)
Caused by: java.lang.ClassNotFoundException: cn.hutool.core.lang.Consoleat java.net.URLClassLoader.findClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)... 1 moreD:\demo01>java -cp ".;*" com.example.Main
Hello World
hello world by hutool!

可以看到,当我们指定为-cp ".;*.jar"时,会发现*.jar并没有解析到我们对应的jar包,但是响应的 -cp .;*却解析到的对应的jar包,因此通配符*.jar是无效的,这里可能是因为JDK版本的原因或者操作系统的原因吧,不太明白,这里暂且估算一个原因,下面是 java 命令的帮助说明截取:

    -cp <目录和 zip/jar 文件的类搜索路径>-classpath <目录和 zip/jar 文件的类搜索路径>用 ; 分隔的目录, JAR 档案和 ZIP 档案列表, 用于搜索类文件。
  • 当指定为目录时(如 .)
    • 搜索目录下的所有字节码文件并解析为类
  • 当指定为 jar 或 zip 压缩包时
    • 读取压缩包并解析其中所有的字节码文件并解析为类
  • 当指定为通配符*
    • 搜索当前或者目录下的所有以zip/jar结尾的压缩包并解析(不会递归解析子目录)

我猜JVM在解析的过程中,当指定为文件或者文件的通配符时,本身只会解析jar包和zip压缩包;当指定为目录时,则会解析目录下的所有字节码文件并加载为类。因此我们不在需要特别指定.jar为文件的后缀了,而如果指定的 .jar 作为文件的后缀时 JVM反而会去尝试解析 hutool-all-5.4.3.jar.jar文件,但由于没有这个文件,自然而然解析不到了。

问题3. 通配符*会不会解析当前目录的子目录下的 jar包?

不会,*只会解析当前目录下的 jar 包,至于子目录下的 jar 包还需要另外指定。

问题4. -cp 参数 与 -jar参数能否一起使用?

简单来说,是不能一起使用的,两者加载 classpath 是不一致的,前者 -cp选项在加载 jar 包和 class 类文件时,是通过后面拼接的参数来加载的,相对的 -jar 选项在加载 jar包时则是获取配置文件中设置的 classpath 从而进行加载。

当指定了 -jar 选项后,JVM不再从 -cp 选项中指定的jar包路径和 类路径 中加载 jar 包,因此同时设置 -cp 参数 和-jar 参数的结果是 -cp 参数相当于没有设置。

问题5.-jar 参数是如何加载 jar包的?

以一个命令为例:

  java -jar main.jar

执行该命令时,JVM 会从 main.jar 包中的检索 META-INF\MANIFEST.MF文件,然后在该文件中,有一个叫Class-Path的参数,它指定了java -jar命令执行的类路径。
以下是一个META-INF.MF清单文件

Manifest-Version: 1.0
Class-Path: . cmd_lib/commons-lang3-3.7.jar
Main-Class: com.yveshe.PackageClass
Name: java/util/

Manifest-Version:

用来定义manifest文件的版本,例如:Manifest-Version: 1.0

Main-Class

定义jar文件的入口类,该类必须是一个可执行的类(包含main方法的类),一旦定义了该属性即可通过 java -jar x.jar来运行该jar文件。
运行Jar: java -jar yveshe.jar
当运行上述命令时JVM将在yveshe.jar文件中的MANIFEST.MF文件中查找Main-Class属性的值,并尝试运行该类。如果在yveshe.jar文件中未包含Main-Class属性,则上述命令将生成错误。

Class-Path

指定jar包的依赖关系,classLoader会依据这个路径来搜索class
默认是相对路径,相对该jar所在的父文件夹.
可以在其manifest 文件中为JAR文件设置CLASSPATH。属性名称叫作类路径,必须在自定义清单文件中指定。 它是一个空格分隔的jar文件,zip文件和目录的列表。(不区分系统都是以空格来分隔多个jar文件)以下是一个属性配置例子:

Class-Path: . hutool-core.jar file:/c:/hutool/hutool-json.jar http://www.example.com/hutool-date.jar

这条命令配置了该main.jar依赖如下jar包:

  • . ---- 表示当前目录下的所有类文件
  • hutool-core ---- 表示当前jar包目录下的 hutool-core.jar jar包;
  • file:/c:/hutool/hutool.-json.jar一个使用文件协议文件指定的 jar 包;
  • http://www.example.com/hutool-date.jar 使用HTTP协议的下载的 jar包;

注意: 当使用java命令使用-jar(比如java -jar main.jar)选项运行JAR文件时
将忽略jarmanifest文件之外的任何CLASSPATH设置。

书写注意

  • 每行的:(冒号)用来分隔键值对,冒号后边一定要跟一个空格。
  • MANIFEST.MF清单文件必须以一个空白行结束。
  • Class-Path里边的内容用空格分隔而不是逗号或者分号
  • 每行不能超过七十多的字符。

参考资料

关于Java -cp引用jar是否支持通配符
java命令 : java -jar 和 java -cp
Setting the class path(官方文档)
关于Java -cp引用jar是否支持通配符
classpath和jar

http://www.wooajung.com/news/35270.html

相关文章:

  • 群晖可不可以做网站用千牛怎么做免费推广引流
  • 济南做网站公司电话优秀企业网站模板
  • 外贸网站推广优化百度引擎
  • 自己做的网站怎么被搜索出来百度指数查询
  • 唐山建设工程造价信息网站长沙seo网络优化
  • 婚礼网站建设网站seo诊断报告
  • 有网站如何做直播长沙网址seo
  • 石家庄 外贸网站建设steam交易链接怎么获取
  • 奢华网站模板宣传网站站点最有效的方式是
  • 如何用小米路由器做网站怎么自己开发网站
  • 做网站好赚钱吗被忽悠去做网销了
  • 宝山宜昌网站建设软文是什么样子的
  • 快速优化网站排名的方法成功营销十大经典案例
  • 如何鉴定网站做的好坏网页制作软件下载
  • 美食网站首页设计2021年度关键词有哪些
  • 中心网站建设方法房地产新闻最新消息
  • 武汉企业网站推广报价手机网站制作软件
  • 做五金外贸哪个网站比较好代做百度收录排名
  • 上海网站建设公司网站建设无锡百度正规推广
  • 深圳做网站好的公司百度客服怎么联系
  • 成都房价谷歌优化是什么意思
  • 网站里的注册怎么做杭州关键词自动排名
  • 新建网站百度搜不到媒体资源
  • 2023年全国疫情最新消息刷移动关键词优化
  • 个人网站做贷款广告网页seo优化
  • 建筑公司企业如何成功提升网页优化排名
  • 门户网站开发案例上海seo优化公司
  • 不提供花架子网站 我国内最新新闻消息今天的
  • 网站续费协议常州网站推广排名
  • mac163网站建设seo公司优化