(学无止境) java 命令行运行 class 文件

(一) 参数: -cp 指定 classpath 的路径,点是代表当前路径

有时会报错 "java 找不到或无法加载主类", 是因为未指定 classpath, 无法找到对应的类;

如果是启动 jar 包中的主类,有可能是 jar 损坏 (自己曾遇到过这样的情况)

 

1.java 指令默认在寻找 class 文件的地址是通过 CLASSPATH 环境变量中指定的目录中寻找的。

2. 我们忽略了 package 的影响。见以下的第二点

 

 

 

 

(二) 他山之石:

使用 java 命令运行 class 文件提示 “错误:找不到或无法加载主类 “的问题分析

以下内容来参考自: https://www.cnblogs.com/guohu/p/11101285.html, 如有侵权,请联系删除. 

 

有时候我们需要直接用 jdk 提供的 java 命令来执行 class 文件让软件运行起来,特别是很多初学者,但经常会发现如下提示:

用 eclipse 或用 ant 则没有问题。

其实原因很简单,我们忽略了 2 个细节。

1.java 指令默认在寻找 class 文件的地址是通过 CLASSPATH 环境变量中指定的目录中寻找的。

2. 我们忽略了 package 的影响。

第一个问题好解决:

我们直接在 CLASSPATH 环境变量中加入 “.;” 即可。“.” 的意思是搜索当前目录

第二个问题看下面分析:

看下面两个类

  

                   类 A                                                                   类 B

类 A 和类 B 的唯一差别就是没有定义包名

我们的工程路径是 D:\HelloWorld, 在 HelloWorld 文件夹中建立一个 src 文件夹,类 B 的源代码文件就放在 src 中。用 javac 编译完以后

会在 src 文件夹中生成 NewsManager.class, 如下

执行如下:

 现在我们再把源代码换成类 A

为什么加入了 package 后就不对了呢?

类 A 中 package 的路径是 org.will.app.main。按照 java 规定,我们应该按照 package 定义的路径来存放源文件,类 A 应该放入:

src\org\will\app\main 下,如下:

然后我们编译执行:

依然有问题,为什么,其实大家再回去看看 java 的书籍就会发现,一个类的全名应该是包名 + 类名。类 A 的全名:org.will.app.main.NewsManager

好的,再试试:

还是不对。为什么?

仔细看上面的图,我们在 main 目录下让 java 命令去执行 org.will.app.main.NewsManager, 其实它会以为类的路径是:

D:\HelloWorld\src\org\will\app\main\org\will\app\main\NewsManager,大家看到了吧,路径重复了。

所以,我们应该在 src 下面来这样执行:

成功!

总结:

一、java 执行 class 文件是根据 CLASSPATH 指定的地方来找,不是我们理解当前目录。如果希望它查询当前目录,需要在 CLASSPATH 中加入 “.;”, 代表当前目录。

二、java 执行 class 文件对 package 的路径是强依赖的。它在执行的时候会严格以当前用户路径为基础,按照 package 指定的包路径转化为文件路径去搜索 class 文件。各位同学以后注意就 OK 啦。至于网上说的要在 CLASSPATH 要加各种包等等都是泛泛而谈,真正静下心分析这个问题的资料不多。很多都没有说到点子上,会误导人的。

-jar 参数运行应用时,设置 classpath 的方法

转自 https://blog.csdn.net/sayyy/article/details/81120749

前言

  • 期望在 java -jar 命令执行 java 程序时,能够指定 classpath

分析

因为使用 “-jar” 选项(形如:java -jar xxx.jar )来运行一个可执行的 jar 包时,jar 包会覆 “-cp” 的值。
换句话说,-jar 后面所跟的 jar 包的优先级别最高。如果指定了 - jar 选项,所有环境变量和命令行制定的搜索路径都将被忽略。JVM APPClassloader 将只会以 jar 包为搜索范围.

解决方案

Java 命令行提供了如何扩展 bootStrap 级别 class 的简单方法.

  • -Xbootclasspath: 完全取代基本核心的 Java class 搜索路径。不常用,否则要重新写所有 Java 核心 class
  • -Xbootclasspath/a: 后缀。将 classpath 添加在核心 class 搜索路径后面。常用!!
  • -Xbootclasspath/p: 前缀。将 classpath 添加在核心 class 搜索路径前面。不常用,避免引起不必要的冲突.

示例如下: (分隔符与 classpath 参数类似,unix 使用:号,windows 使用;号,这里以 unix 为例)

 
  1. //特定的jar到classpath
  2. java -Xbootclasspath/a:/usrhome/thirdlib1.jar:/usrhome/thirdlib2.jar -jar yourJarExe.jar
  3. //添加目录到classpath
  4. java -Xbootclasspath/a:/usrhome/thirdlib1/:/usrhome/thirdlib1/ -jar yourJarExe.jar
  5. //添加当前目录(可执行的jar所在的目录)到classpath
  6. java -Xbootclasspath/a:./ -jar yourJarExe.jar
 

扩展知识(转)

自 JDK 1.2 以后,JVM 采用了委托 (delegate) 模式来载入 class.采用这种设计的原因可以参考 http://java.sun.com/docs/books/tutorial/ext/basics/load.html

归纳来讲:是基于 JVM sandbox (沙盒) 安装模型上提供应用层的可定制的安全机制.

Java 虚拟机 (JVM) 寻找 Class 的顺序

1. Bootstrap classes

属于 Java 平台核心的 class, 比如 java.lang.String 等。及 rt.jar 等重要的核心级别的 class. 这是由 JVM Bootstrap class loader 来载入的。一般是放置在 {java_home}\jre\lib 目录下

2. Extension classes

基于 Java 扩展机制,用来扩展 Java 核心功能模块。比如 Java 串口通讯模块 comm.jar. 一般放置在 {Java_home}\jre\lib\ext 目录下

3. User classes

开发人员或其他第三方开发的 Java 程序包。通过命令行的 - classpath 或 - cp, 或者通过设置 CLASSPATH 环境变量来引用.JVM 通过放置在 {java_home}\lib\tools.jar 来寻找和调用用户级的 class. 常用的 javac 也是通过调用 tools.jar 来寻找用户指定的路径来编译 Java 源程序。这样就引出了 User class 路径搜索的顺序或优先级别的问题.

  • 3.1 缺省值:调用 Java 或 javawa 的当前路径 (.), 是开发的 class 所存在的当前目录
  • 3.2 CLASSPATH 环境变量设置的路径。如果设置了 CLASSPATH, 则 CLASSPATH 的值会覆盖缺省值
  • 3.3 执行 Java 的命令行 - classpath 或 - cp 的值,如果制定了这两个命令行参数之一,它的值会覆盖环境变量 CLASSPATH 的值
  • 3.4 -jar 选项:如果通过 java -jar 来运行一个可执行的 jar 包,这当前 jar 包会覆盖上面所有的值。换句话说,-jar 后面所跟的 jar 包的优先级别最高,如果指定了 - jar 选项,所有环境变量和命令行制定的搜索路径都将被忽略.JVM APPClassloader 将只会以 jar 包为搜索范围.
    有关可执行 jar 有许多相关的安全方面的描述,可以参考 http://java.sun.com/docs/books/tutorial/jar/ 来全面了解.

这也是为什么应用程序打包成可执行的 jar 包后,不管你怎么设置 classpath 都不能引用到第三方 jar 包的东西了.

安装的扩展是 Java 运行时环境 (JRE™) 软件的 lib/ext 目录中的 JAR 文件。顾名思义,JRE 是 Java 开发工具包的运行时部分,包含平台的核心 API,但不包含编译器和调试器等开发工具。
JRE 可以单独使用,也可以作为 Java 开发工具包的一部分使用。

JRE 是 JDK 软件的严格子集。 JDK 软件目录树的子集如下所示:

JDK software directory tree

JRE 由图中突出显示的框中的那些目录组成。无论您的 JRE 是独立的还是 JDK 软件的一部分,JRE 目录的 lib/ext 中的任何 JAR 文件都会自动被运行时环境视为扩展。

由于安装的扩展扩展了平台的核心 API,因此请谨慎使用它们。它们很少适合单个或一小组应用程序使用的接口。

此外,由于安装的扩展定义的符号在所有 Java 进程中都是可见的,因此应注意确保所有可见符号都遵循适当的 “反向域名” 和 “类层次结构” 约定。例如, com.mycompany.MyClass 。

posted @ 2024-06-27 09:54  CharyGao  阅读(160)  评论(0)    收藏  举报