Java命令行运行错误: 找不到或无法加载主类

2023-05-16

前言:虽然学习Java语言约有两年多,但在最近需要使用命令行工具编译并运行Java程序时,还是报错了。花费了一些时间,解决了该问题,发现解决方法在初学Java时使用过。一则,为了避免以后再出现同样的问题而浪费不必要的时间;二则,作为使用该语言的程序员,对于该语言的一些基本问题,应该有清晰的理解和认识;三则,网上的一些解决方案,不够完备。有的没有解释问题原因,直接给出答案;有的,未列举出某些常见情况的解决方案。因此,写此文章,让读者可以举一反三,深入理解问题。

一、 问题分析

找不到或无法加载主类,主要原因有两个:

1. 类名错误

2. 类所在位置未添加至类加载路径中

二、 问题解决

本部分将针对在“一”中提出的两个问题发生原因,分别进行分析及处理。并且会介绍java的一些和处理问题相关的基本概念。

1. 类名错误

全限定类名:包名+类名。另外,当包名为空时(即代码不包含package语句),称类所在包为默认包

例如,以下代码的全限定类名为:“com.gzn.demo.HelloWorld”

// 文件名HelloWorld.java
package com.gzn.demo;
public class HelloWorld {
    public static void main(String args[]) {
        System.out.println("hello world");
    }
}

在运行java程序时,全限定类名可以唯一确定该文件,就像是文件系统中路径(相当包名)+文件名(相当类名)可以唯一确定一个文件一样。本质上包名发挥的作用和文件系统中的目录相同,有利于文件分隔避免重名。

现在存在一个问题,Java是如何识别一个类文件的包名的?
实际上,包名的识别是通过文件系统的目录实现的 。例如,上文提到的包名为“com.gzn.demo”的HelloWorld.java文件,该文件在文件系统中的位置为 “com\gzn\demo”,编译后的HelloWorld.class也在"com\gzn\demo"目录下,因此,在运行java程序后加载类时,只需在“com\gzn\demo”目录下,查看是否存在要查找的文件即可。简而言之,目录(或路径)名于包名存在一一映射的关系,可认为相等。

在Windows操作系统的命令行下,运行Java代码的语法格式为,注意,此时java命令位于目录com的上一级目录(一般为项目的目录名);类名不能包含扩展名.class

Java 全限定类名
例如java com.gzn.demo.HelloWorld;包名为空则为java HelloWorld

Windows操作系统中还有另一种语法格式(其他系统未必可以),不常用,使用反斜杠代替了点好,之所以没用正斜杠,个人猜测是为了和系统的文件分隔符进行区分:

例如Java com/gzn/demo/HelloWorld; 包名为空则为java HelloWorld

可能出错情况一 :在命令行运行java程序时,类名包含了扩展名

在helloworld项目目录下运行java命令,HelloWorld.class文件在“com\gzn\demo”目录下,即包名为com.gzn.demo,上文已介绍,不在赘述。
C:\Users\gzn\helloworld>java com.gzn.demo.HelloWorld.class
或者包名为空
C:\Users\gzn\helloworld> java HelloWorld.class
上述写法,会出现报错,原因是它不符号java运行程序的语法格式,java可能把“HelloWorld.class”作为一个整体类名处理,那么要查找的文件可能是“HelloWorld.class.class”,显然是找不到的。

可能出错情况二 :运行Java命令时未指明全限定类名的包名部分或指明了包名但Java命令运行的位置不正确
假设HelloWorld.class,包名为com.gzn.demo,所在位置为: C:\Users\gzn\helloworld\com\gzn\demo
运行以下命令
C:\Users\gzn\helloworld\com\gzn\demo>java HelloWorld
运行命令后,会在当前目录下,查找并读取该文件后,发现该类为“com.gzn.demo.HelloWorld”(全限定类名唯一确定一个类,上文已介绍)与我要运行的类“HelloWorld”并不是同一类,因此,找不到要运行的类。
于是,很自然的一个想法是运行以下命令
C:\Users\gzn\helloworld\com\gzn\demo>java com.gzn.demo.HelloWorld
包名和文件名是一一映射的(上文已介绍),运行命令后,会从命令所在位置开始(即以命令所在位置为相对路径),查找“com\gzn\demo\”路径下的HelloWorld文件。由于“C:\Users\gzn\helloworld\com\gzn\demo”路径下根本不存在目录“com”(更不用说gzn\demo),因此,找不到运行的类。

正确的运行命令的方法,呼之欲出,只需改变命令的运行位置即可,如下所示
C:\Users\gzn\helloworld>java com.gzn.demo.HelloWorld
运行命令后,会在“com\gzn\demo”路径下找到并读取HelloWorld文件,发现该类的全限定名为“com.gzn.demo.HelloWorld”,查找的类正是Java想要运行的类。


以上是比较初级的出错情况,下文将要介绍相对比较高级的出错情况,这也是其他博文未曾给出解决方案的情况。同时还会介绍classpath的概念,及使用方法。加油!

2. 类所在位置未添加至类加载路径中

类加载路径(Classpath):当你的程序依赖第三方或者自己写的类文件时,需要指出上述文件的所在位置,即类加载路径。Java虚拟机的类加载器会在你指定的路径中,查找你的程序所依赖的类文件(依赖的类文件 在import语句中指定)

classpath可以通过以下两种方式指定:

方式一:配置环境变量

  这种方式是初学Java者肯定了解的方式,通常在下载完JDK后就会进行配置。然而在JDK1.5之后,官方已不建议使用这种方式来指定类加载路径,原因后文扩展部分会谈及。

在这里插入图片描述
说明:“.”表示在当前目录,即java等命令运行时所在目录;
dt.jar是关于运行环境的类库,主要是用于swing的包,如果不使用可以不配置;
tools.jar是工具类库,它在编译和运行一个类时被使用

方式二:java命令的-cp(或-classpath)参数指定(官方建议)

这种方式是JDK1.5后官方建议的方式。当你在命令行下运行java命令时,如果没有指定-classpath参数,那么默认使用环境变量中设置的ClASSPATH。官方建议,你在运行每个程序时,为其显示设置所依赖的类文件所在的位置,而不是使用“全局”性质的环境变量中CLASSPATH。一旦你运行程序时指定了-classpath参数,环境变量中的CLASSPATH就不会在使用,而是使用你参数的classpath。实际上,JDK1.5以后,官方已经不建议配置CLASSPATH环境变量。

语法格式如下:

java -cp <路径1;路径2;…> 全限定类名

路径:依赖的文件所在的绝对路径(或相对路径),如果类文件在jar包中,路径后还要写上jar包的名字,例如“C:\users\gzn\mylib\algs4.jar”
注意,“.”代表当前路径,即java命令运行时所在路径。

可能出错情况三 :存在依赖外部jar包时,命令行运行java命令,classpath参数中只是添加了外部jar包路径,没有添加当前目录“.”,导致要运行的类文件找不到。

或者,程序在IDE(eclipse、IDEA等)开发工具中可以运行,但是在命令行下不能运行,情况相同。

在某篇高赞博文中,依然存在的问题
在这里插入图片描述
下面,通过问题在现的方式,讲解解决方法。
项目简介:HelloWorld.java程序,位置“C:\Users\gzn\helloworld\com\gzn\demo”,依赖algs4.jar(位置C:\Users\gzn\helloworld)中的edu.princeton.cs.algs4.StdOut类,调用了该类的print函数,其API如下

public class StdOut
public static void print(String s); 打印输出指定的字符串

HelloWorld.java

package com.gzn.demo;
import edu.princeton.cs.algs4.StdOut;

public class HelloWorld {
	public static void main(String args[]) {
		StdOut.print("Hello World!");
	}
}

项目结构如下图所示:
在这里插入图片描述
在命令行运行程序时,存在外部依赖,不仅要在-cp (或-classpath)中指明依赖的路径,还有把当前路径加进去。因为当你指定了-classpath参数后,环境变量失效,于是环境变量CLASSPATHY中设置的当前目录“.”也就不能用了。虚拟机类加载器加载类的路径只能在classpath类加载路径指明的位置中查找,如果路径中没有添加当前目录“.”,也就是当前要运行的类所在位置没有添加到类加载路径中,显然会查找不到类。解决方法如下图所示:
在这里插入图片描述

三、扩展知识

1. JDK目录结构及环境变量介绍

JDK目录介绍
在这里插入图片描述

初学者环境变量配置如下:

变量名
CLASSPATH.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tool.jar (注,jdk1.5后无需配置)
JAVA_HOMED:\jdk8(JDK安装目录,视个人安装情况而定)
Path%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin

Path为命令行工具指定命令的查找路径。命令的本质是可执行程序,设置后可以在命令行工具下运行java、javac、javah等常用的命令;
JAVA_HOME 指定了JDK(Java开发工具包)路径。设置后,无论是编译还是运行程序,类加载器都会从相应的目录中加载需要的类库。如运行javac编译命令,会从”%JAVA_HOME%\lib\tool.jar”加载需要的类;通过java命令运行程序,会从“%JAVA_HOME%\jre\lib\rt.jar”加载程序依赖的类;Java虚拟机会从“%JAVA_HOME%\jre\lib\ext\”加载依赖的类。

jdk中的函数库lib称为Java的标准库,指定了JAVA_HOME环境变量后就可以使用了,编译和运行会自动在相应位置查找依赖的类。而第三方库(如mysql-connector-java-5.1.40.jar)和用户自己定义的类库 在编译和运行时,需要在-cp类加载路径参数中指明库的位置。

2. 为什么jdk1.5后不需要配置环境变量了?

此部分内容参考自Java开发环境不再需要配置classpath!

在JDK1.5之前,是没有办法在当前目录下加载类的(找不到 JDK目录下lib文件夹中的.jar文件),所以我们需要通过配置classpath,但JDK1.5之后,JRE能自动搜索目录下类文件,并且加载dt.jar和tool.jar的类。

The class path tells the JDK tools and applications where to find third-party and user-defined classes that are not extensions or part of the Java platform. See The Extension Mechanism at
类路径告诉JDK工具和应用程序在哪里可以找到第三方和用户定义的类,这些类既不是Java平台的扩展,也不是Java平台的一部分。参见扩展机制

If you upgrade from an earlier release of the JDK, then your startup settings might include CLASSPATH settings that are no longer needed. You should remove any settings that are not application-specific, such as classes.zip. Some third-party applications that use the Java Virtual Machine (JVM) can modify your CLASSPATH environment variable to include the libraries they use. Such settings can remain.

如果您从JDK的早期版本升级,那么您的启动设置可能包括不再需要的类路径设置。您应该删除任何与应用程序无关的设置,比如classes.zip。一些使用Java虚拟机(JVM)的第三方应用程序可以修改类路径环境变量,以包含它们使用的库。这样的设置可以保留。

You can change the class path by using the -classpath or -cp option of some Java commands when you call the JVM or other JDK tools or by using the CLASSPATH environment variable. See JDK Commands Class Path Options. Using the -classpath option is preferred over setting the CLASSPATH environment variable because you can set it individually for each application without affecting other applications and without other applications modifying its value. See CLASSPATH Environment Variable.

在调用JVM或其他JDK工具时,可以使用一些Java命令的-classpath或-cp选项,或者使用CLASSPATH环境变量,来更改类路径。参见JDK命令类路径选项。使用-classpath选项优于设置CLASSPATH环境变量,因为您可以为每个应用程序单独设置它,而不影响其他应用程序,也不需要其他应用程序修改它的值。参见CLASSPATH环境变量。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java命令行运行错误: 找不到或无法加载主类 的相关文章

  • 由chmod改系统文件权限引ssh登录报ssh_exchange_identification: read: Connection reset by peer无法登陆问题

    root用户下在给某个文件夹下的所有文件改权限的时候 xff0c 用了chmod R 命令 xff0c 咋一看这个命令没啥很正常 xff0c 也能执行 xff0c 但是后面的提示让人感觉很不对劲 xff0c 因为yang下文件没这么多 xf
  • mysql中find_in_set()函数的使用

    在做电商项目时 xff0c 不知你有没有遇到这样的一种情况 xff0c mysql数据库中商品表tb product里面有个字段type xff0c 它存储的是商品类型 xff0c 比如 1 xff1a 热门推荐2 xff1a 精选推荐3
  • shell设置变量与脚本返回值

    Linux中的本地变量和环境变量 本地变量 查看本地变量 set 设置本地变量 x 61 34 123 34 环境变量 查看环境变量 env 设置环境变量 x 61 34 123 34 export x 注意 xff1a 变量与等号 等号与
  • Docker 环境准备好这些,工作就完成了一半

    Docker官网yum源 xff1a http yum dockerproject org repo main 支持不同版本 1 span class token punctuation span 关闭防火墙 systemctl stop
  • 习题5-7 使用函数求余弦函数的近似值 (15 分)

    本题要求实现一个函数 xff0c 用下列公式求cos x 的近似值 xff0c 精确到最后一项的绝对值小于e xff1a cos x 61 x 0 0 x 2 2 43 x 4 4 x 6 6 43 函数接口定义 xff1a double
  • 6-12 二叉搜索树的操作集 (30 分)

    本题要求实现给定二叉搜索树的5种常用操作 函数接口定义 xff1a BinTree Insert BinTree BST ElementType X BinTree Delete BinTree BST ElementType X Posi
  • C++ CAS 操作

    C 43 43 中的 CAS 操作用于操作原子变量 xff0c 它是 atomic lt T gt 的成员函数 span class token macro property span class token directive hash
  • 习题6-6 使用函数输出一个整数的逆序数 (20 分)

    本题要求实现一个求整数的逆序数的简单函数 函数接口定义 xff1a int reverse int number 其中函数reverse须返回用户传入的整型number的逆序数 裁判测试程序样例 xff1a include lt stdio
  • 数据结构之各种常用结构体总结

    一 线性表 define MaxSize 100 表长度初始定义 typedef struct ElemType data MaxSize 或者指示动态分配数组的指针Elemtype data int length 数组最大容量和长度 Sq
  • 习题2.7 弹球距离 (15 分)

    设有一个球从高度为h米的地方落下 xff0c 碰到地面后又弹到高度为原来p倍的位置 xff0c 然后又落下 xff0c 再弹起 xff0c 再落下 请编写函数求初始高度为h的球下落后到基本停下来 xff08 高度小于给定阈值TOL xff0
  • 习题7-3 判断上三角矩阵 (15 分)

    上三角矩阵指主对角线以下的元素都为0的矩阵 xff1b 主对角线为从矩阵的左上角至右下角的连线 本题要求编写程序 xff0c 判断一个给定的方阵是否上三角矩阵 输入格式 xff1a 输入第一行给出一个正整数T xff0c 为待测矩阵的个数
  • python计算黑白图像像素值

    span class token function import span numpy as np span class token function import span cv2 span class token comment 读入图
  • python将文件夹中图像生成file list

    按行排列 xff0c 图像路径 span class token function import span os span class token function import span argparse span class token
  • Markdown插入图片 详细例子(本地图片,网络图片,base64) Windows

    网上一番搜索 xff0c 领略到基本所有回答 xff0c 都是一样的 xff0c 简简单单的介绍 而且 xff0c TMD xff0c 插入图片答案的本地路径 xff0c 都是回答的是Linux或Mac OS系统的路径 xff0c 诸如 x
  • Pixhawk学习笔记(2)——问题汇总

    1 遥控器校准时 xff0c 拨动摇杆 xff0c 上位机通道数据不变化 解决方法 xff1a PPM编码器上有一个跳线需短接 xff0c 短接后才可通过编码器对遥控器接收机供电 供电前PPM编码器模块上蓝灯快闪 xff0c 供电后变为慢闪
  • 在FPGA中使用Verilog实现I2C通信

    按照I2C标准的官方时序 可以看出时序看起来很简单 xff0c 不过它严格的按照时序要求来传送数据 xff0c 马虎不得的 xff0c 特别是起始和停止的条件 xff0c 起始必须要时钟线SCL为高电平时数据线SDA拉低 xff1b 而停止
  • Pixhawk学习笔记(5)——PX4FLOW光流传感器调试过程记录

    先使用qgc地面站查看光流图像及数据 xff0c 能看到不错的图像和波形 烧写官网固件后 xff0c 接入pixhawk飞控 xff0c 使用apm固件 xff0c 勾选启用光流 xff0c 超声波选用pix iic xff0c 在miss
  • 数据结构—布隆过滤器

    布隆过滤器可以快速地告诉你 xff1a 某个值一定不存在 xff0c 以及某个值可能存在 布隆过滤器是基于位图和哈希函数 xff08 如 xff0c MurmurHash xff09 来实现了 此处假设有两个哈希函数 hash 1 hash
  • PX4/Pixhawk---快速成为开发者(Windows)

    1 快速成为开发者入门教程 xff08 翻译 xff09 官方 1 1 编译环境 xff08 1 xff09 安装 MSysGIT 安装完成后 xff0c 配置GIT 安装注意 安装过程中除了下面一步外 xff0c 其他的步骤都采用默认安装
  • Cdence版图设计手册

    Cadence版图设计 工作站常用命令 一 在terminal窗口键入的基本命令 xff1a 1 ls xff1a 列出目录下所有文件 2 clear xff1a 清除terminal窗口里的内容 3 pwd xff1a 显示目前工作的目录

随机推荐

  • Pixhawk开发手册

    一 常见问题 xff1a 1 遥控器校准时 xff0c 拨动摇杆 xff0c 上位机通道数据不变化 解决方法 xff1a PPM编码器上有一个跳线需短接 xff0c 短接后才可通过编码器对遥控器接收机供电 供电前PPM编码器模块上蓝灯快闪
  • 浅谈四轴PID调试心得

    以下内容转自阿莫论坛 xff0c 写得很详细 xff0c 是调试大四轴的 小四轴调试也可参照着调 PID调试心得 本人不是自动化出身 xff0c 也没有受过专业训练 xff0c 都是自己摸索 xff0c 在这里浅述一下自己的PID参数整定心
  • rctimer二轴云台及云台控制板调试(Simple bgc 8位破解板)

    前段时间在鬼王家抢了rctimer的二轴云台和控制板 xff0c 感觉做工很精良 这几天有空了就调试下 整个过程比较容易 xff0c 首先要准备好usbisp烧写器 xff0c 和一根阶梯形的micro usb线 先刷bootloader
  • APM和PIX飞控日志分析入门贴

    我们在飞行中 xff0c 经常会碰到各种各样的问题 xff0c 经常有模友很纳闷 xff0c 为什么我的飞机会这样那样的问题 xff0c 为什么我的飞机会炸机 xff0c 各种问题得不到答案是一件非常不爽的问题 xff0c 在APM和PIX
  • 微电子及集成电路设计常用问题总结(考研面试向)

    mos管的沟道长度调制效应 xff1f 源极导致势垒下降 xff1f 衬底电流体效应 xff1f 衬底偏执效应 xff1f 速度饱和效应 xff1f 举例典型的trade off xff1f mos amp bjt的工作曲线 xff1f 加
  • YOLO详解

    转载自 xff1a https zhuanlan zhihu com p 25236464 从五个方面解读CVPR2016 目标检测论文YOLO Unified Real Time Object Detection 创新 核心思想 效果 改
  • 使用微信监管你的TF训练

    以TensorFlow的example中 xff0c 利用CNN处理MNIST的程序为例 xff0c 我们做了下面一点点小小的修改 1 xff0c 首先导入了itchat和threading两个包分别用于微信和县线程 xff08 因为要有一
  • 你应该知道的9篇深度学习论文(CNNs 理解)

    当时看到英文的博客 xff0c 本想翻译给感兴趣的同学们看看 xff0c 没想到已经有人翻译 xff0c 于是进行了转载 xff0c 留给自己和更多的人学习 xff0c 本文仅供参考 英文博客 xff1a https adeshpande3
  • JS笔记(==和===的介绍)

    61 61 和 61 61 61 介绍 61 61 关系运算符 等于 用于比较两个操作数是否相等的 相等为true xff0c 否则为false 61 不等于 61 61 61 xff1a 绝对等于 用于比较两个操作数是否相等的 相等为tr
  • 全国大学生电子设计竞赛B题感悟-优象光流篇

    今年是2019年电赛国赛年 xff0c 这本是是一个很好的机会冲击国家奖的 xff0c 但是由于个人视野太窄 xff0c 眼光不够长远而错失良机 今年测评结束的时候我就已经预感到了结果 xff0c 记得比赛前去提交作品的时候 xff0c 大
  • 滑模控制以及系统动力学与控制论(1)

    维基百科里是这样定义系统 System 的 System from Latin syst ma in turn from Greek syst ma is a set of entities real or abstract compris
  • 安装docker

    首先信任 Docker 的 GPG 公钥 sudo apt key adv keyserver hkp p80 pool sks keyservers net 80 recv keys 58118E89F3A912897C070ADBF76
  • 我的AI之路(39)--使用深度相机之小觅深度相机

    小觅深度相机的SDK代码在github上 小觅相机的支持库需要从这里https github com slightech MYNT EYE D SDK下载SDK源码后本地编译后再安装 xff0c Ubuntu上的步骤是 xff1a 1 如果
  • DeepSORT C++版的一个bug

    DeepSORT的官方python版实现是https github com nwojke deep sort xff0c C 43 43 版的DeepSORT中https github com shaoshengsong DeepSORT这
  • 使用sudo运行vncserver后导致Ubuntu循环登录进入不了桌面的问题原因及解决办法

    因需要多人同时登录到机器人的Ubuntu主机调试 xff0c 于是安装VNC xff0c 不记得N年以前怎么做的了 xff0c 于是按照网上某文说的先 xff1a sudo apt get install xfce4 插一句 xff1a 也
  • CAS6.1 配置连接数据库,以及修改自定义的密码验证(SpringSecurity)

    一 cas 配置数据库 1 在build gradle中引入jar dependencies Other CAS dependencies modules may be listed here compile 34 org apereo c
  • 怎样学好数电

    随着社会的进步和科学技术的发展 xff0c 数字系统和数字设备已广泛应用于各个领域 xff0c 大规模 xff0c 超大规模集成电路技术的不断完善使得数字电路在现代电子系统的比重越来越大 xff0c 数字电路建立了根本是信号的数字处理 xf
  • 嵌入式经典面试题之选择题

    一 单项选择题 1 如下哪一个命令可以帮助你知道shell命令的用法 xff08 A xff09 A man B pwd C help D more 2 Linux分区类型默认的是 xff1a xff08 B xff09 A vfat B
  • 自定义 Windows RE 体验

    发布时间 2009年10月 更新时间 2009年10月 应用到 Windows 7 Windows Server 2008 R2 https technet microsoft com zh cn library dd744576 v 61
  • Java命令行运行错误: 找不到或无法加载主类

    前言 xff1a 虽然学习Java语言约有两年多 xff0c 但在最近需要使用命令行工具编译并运行Java程序时 xff0c 还是报错了 花费了一些时间 xff0c 解决了该问题 xff0c 发现解决方法在初学Java时使用过 一则 xff