javac学习-“Error: Could not find or load main class Main”

2 篇文章 0 订阅
1 篇文章 0 订阅

javac学习-“Error: Could not find or load main class Main”

一、上报错代码

package hello;

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

编译后,运行报错

$ javac HelloWorld.java
$ java HelloWorld
Error: Could not find or load main class HelloWorld

二、查找问题

2.1 查找java入门的代码示例

百思不得其解,到在线学习java的网站上看了下代码,我的代码只是多了package,难道是这个产生的这个问题吗?

示例代码

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}
$ javac HelloWorld.java
$ java HelloWorld
Hello World

也给网站上加一个package,一样报错。

Error: Could not find or load main class Main
Caused by: java.lang.NoClassDefFoundError: hello/Main (wrong name: Main)

Exited with error status 1
2.2 csdn文章大佬分享

在一个csdn的帖子里说到了classpath的问题,但是没有说透,写的太繁琐了。但是给的一个链接对classpath的介绍说的很好。

csdn 帖子:https://blog.csdn.net/abcdu1/article/details/86693800

stackover帖子:https://stackoverflow.com/questions/18093928/what-does-could-not-find-or-load-main-class-mean

这个stackover帖子很清晰的罗列了包罗万象的java编译出错的原因。

答案可能在其中,但是我没有得到很清晰的答案,继续上下而求索。

三、fire in the hole

最后在百度的知道里找到很直接很暴力的答案 (百度知道很难得提供了正确的信息)。

https://zhidao.baidu.com/question/213065551.html

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b2dyJNQ0-1607748802719)(…/image/image-20201212115120286.png)]

这里清晰的说出了,如果有package,那么你的java文件所在的目录结构就要和package对应

我大概明白了我的代码运行错误的原因了。常常用idea intellij搬砖,已经忘记了来的路了。其实intellij软件会根据我们命名的package,建立对应的目录,包括编译出的class文件的路径也是按照这个结构。

对照着分析着裸奔的java代码和工程里的java文件路径,猜测java在执行代码的时候,package和目录应该这都是要一一对应的。查看了大佬关于jvm中的说明,并提到了“双亲委派机制”中的过程。jvm中照这个package,转换成目录来查找class的

classpath只是一个基点,package是以classpath的相对路径。

以下是URLClassLoader.java中的部分代码。

/* The search path for classes and resources */
private final URLClassPath ucp;

protected Class<?> findClass(final String name)
  throws ClassNotFoundException
{
  final Class<?> result;
  try {
    result = AccessController.doPrivileged(
      new PrivilegedExceptionAction<Class<?>>() {
        public Class<?> run() throws ClassNotFoundException {
          String path = name.replace('.', '/').concat(".class");
          Resource res = ucp.getResource(path, false);
          if (res != null) {
            try {
              return defineClass(name, res);
            } catch (IOException e) {
              throw new ClassNotFoundException(name, e);
            }
          } else {
            return null;
          }
        }
      }, acc);
  } catch (java.security.PrivilegedActionException pae) {
    throw (ClassNotFoundException) pae.getException();
  }
  if (result == null) {
    throw new ClassNotFoundException(name);
  }
  return result;
}

四、测试

于是我新建了hello目录,将HelloWorld.java扔入其中,不进去hello目录,执行编译和运行的命令。

$ mkdir hello
$ mv HelloWorld.java hello
$ javac hello/HelloWorld.java 
$ java hello.HelloWorld
Hello World

$ rm HelloWorld.class 
$ java hello.HelloWorld
Hello World

$ java hello/HelloWorld
Hello World

结果显示正确。

打算继续测试-cp和package的关系,进入hello目录,再试了一下

$ cd hello/
$ java HelloWorld
Error: Could not find or load main class HelloWorld

$ java -cp ../ hello/HelloWorld
Hello World

$ javac HelloWorld.java 
$ java -cp ../ hello/HelloWorld
Hello World

$ java -cp ./ hello/HelloWorld
Error: Could not find or load main class hello.HelloWorld

$ java HelloWorld
Error: Could not find or load main class HelloWorld

五、结论

通过以上测试,当代码中有指定package时,有几点需要注意的:

5.1 目录结构和package要对应

目录结构和package要对应,如 package hello,就一定更要把class文件放在hello目录下

5.2 在运行的时候一定要带上全称:package + 类名

如:hello/HelloWorld 或 hello.HelloWorld

5.3 classpath路径问题

classpath不指定,默认表示是当前文件夹,在有package的情况下,一定要可以通过classpth + package找到你要执行的class-cp表示指定classpath路径

​ (1)如果和class文件在同一目录,那么就要把classpath改写到上一级目录:

​ java -cp …/ hello/HelloWorld

​ (2)如果和class文件同一个目录,可以

​ java -cp ./ hello/HelloWorld

​ (3)并且,因为是同一目录,可以省略-cp,

​ java hello/HelloWorld

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值