运行 Java 程序

Undefined443 / 2024-02-18 / 原文

编译

javac HelloWorld.java  # 获得 Java 字节码文件 HelloWorld.class

运行

java HelloWorld  # 运行当前目录下的 HelloWorld.class 文件

附加说明

如果你的 Java 类在包内,你需要将 package 声明添加到你的 Java 文件顶部,并且在编译和运行时,你需要指定完整的类路径。假设你的类声明了 package com.example;,那么编译和运行命令应该相应地调整:

package com.example;

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

编译和运行:

# 在项目根目录运行下面的命令
javac com/example/HelloWorld.java  # 编译
java com.example.HelloWorld  # 运行

在编译的时候,确保你的工作目录在包结构的顶层,或者指定 -d 选项让 javac 自动生成需要的目录结构。

运行更加复杂的 Java 类

如果你的程序使用了外部库,那么在编译和运行时,你还需要包含这些库的路径到 classpath 中。如:java -cp path/to/classfile HelloWorld。(如果不加 -cp 选项,默认的 classpath 为当前目录 .

classpath 为 Java 解释器指明类的位置

例:

我写了一个 maxmind.IpDemo(下称 IpDemo)类,该类的 .class 文件位于项目根目录的 maxmind 目录下,该类中使用了 com.fasterxml.jackson.databind.JsonNode(下称 JsonNode)类以及 com.maxmind.db.Reader (下称 Reader)类。

源代码如下:

package maxmind;

import java.io.File;
import java.net.InetAddress;

import com.fasterxml.jackson.databind.JsonNode;
import com.maxmind.db.Reader;

public class IpDemo {
    public static void main(String[] args) throws Exception {
        File database = new File("resources/Country.mmdb");
        Reader reader = new Reader(database);
        InetAddress address = InetAddress.getByName("114.114.114.114");
        JsonNode response = reader.get(address);
        System.out.println(response);
        reader.close();
    }
}

其中 JsonNode 类及其依赖类分别位于 jackson-databind-2.16.1.jarjackson-core-2.16.1.jarjackson-annotations-2.16.1.jar 三个 jar 包中;

Reader 类位于 maxmind-db-1.2.1.jar 一个 jar 包中;

这些 jar 包位于 Maven 的包仓库的某处。

因此,在运行 maxmind.IpDemo 类时你需要添加如下 classpath

  • JsonNode 类及其依赖类的三个 classpath,即三个 jar 包的位置
  • Reader 类的一个 classpath,即一个 jar 包的位置
  • IpDemo 类自身的 classpath,即项目根目录

即:

java -cp \
    $M2_HOME/com/fasterxml/jackson/core/jackson-databind/2.16.1/jackson-databind-2.16.1.jar: \
    $M2_HOME/com/fasterxml/jackson/core/jackson-core/2.16.1/jackson-core-2.16.1.jar: \
    $M2_HOME/com/fasterxml/jackson/core/jackson-annotations/2.16.1/jackson-annotations-2.16.1.jar: \
    $M2_HOME/com/maxmind/db/maxmind-db/1.2.1/maxmind-db-1.2.1.jar: \
    . \
        maxmind.IpDemo

如果你少写了其中一个 classpath(比如说少写了 jackson-annotations-2.16.1.jar 包的位置),则可能出现如下错误:

Exception in thread "main" java.lang.NoClassDefFoundError: com/fasterxml/jackson/annotation/JsonView
	at com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector.<clinit>(JacksonAnnotationIntrospector.java:37)
	at com.fasterxml.jackson.databind.ObjectMapper.<clinit>(ObjectMapper.java:400)
	at com.maxmind.db.Decoder.<clinit>(Decoder.java:28)
	at com.maxmind.db.Reader.<init>(Reader.java:131)
	at com.maxmind.db.Reader.<init>(Reader.java:116)
	at com.maxmind.db.Reader.<init>(Reader.java:66)
	at com.maxmind.db.Reader.<init>(Reader.java:53)
	at maxmind.IpDemo.main(IpDemo.java:12)
Caused by: java.lang.ClassNotFoundException: com.fasterxml.jackson.annotation.JsonView
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
	... 8 more

表示找不到类定义(即找不到类的 .class 文件)

这里的错误表示找不到 com.fasterxml.jackson.annotation.JsonView 类的定义。根据类名我们猜测它应该位于 jackson-annotations-2.16.1.jar 包中,因此我们需要在 classpath 中添加 jackson-annotations-2.16.1.jar 包的位置。

如果出现错误:

错误: 找不到或无法加载主类 maxmind.IpDemo
原因: java.lang.ClassNotFoundException: maxmind.IpDemo

则表示你没有添加 IpDemo 类的路径,即项目根目录 .