java源码怎么运行

把 `.java` 文件丢给同事,源码运行他双击了一下,源码运行然后问你“怎么没反应”。源码运行这事我见过不止一次。源码运行Java 源码不是源码运行脚本,不能像 `.py` 或 `.sh` 那样直接执行。源码运行它得先被编译成字节码,源码运行再交给 JVM 跑。源码运行这个链条少一环都不行。源码运行

先说你写的源码运行那份 `Hello.java`。它本质上就是源码运行纯文本,和 `.txt` 没区别。源码运行操作系统不认识 `class`、源码运行`public static void main` 这些词。源码运行真正能“跑”的源码运行是 JVM,而 JVM 只认一种东西:`.class` 文件里的字节码。所以第一步永远是编译,不是运行。

编译靠 `javac`。命令很朴素:

javac Hello.java

如果代码没毛病,当前目录会冒出一个 `Hello.class`。这个文件打开是乱码,正常,它是二进制字节码。你可以用 `javap -c Hello` 反汇编看看,里面是一堆 `aload_0`、`invokespecial` 之类的指令。JVM 就是逐条读这些指令干活的。

接下来才轮到 `java` 命令:

java Hello

注意,这里写的是类名 `Hello`,不是 `Hello.class`,也不是 `Hello.java`。新手最容易在这卡住。`java` 命令会去找 `Hello.class`,把它加载进 JVM,然后找 `main` 方法作为入口开始执行。JVM 自己带着一套运行时环境:堆、栈、方法区、垃圾回收器,全都在这时候启动。

那为什么有人觉得 Java 也能“直接运行”?因为 JDK 11 之后,`java Hello.java` 这种写法确实能一把梭。它内部先偷偷编译再执行,看起来像脚本。但这只是语法糖,底层流程没变。你拿它跑一个多文件项目试试,马上露馅。

字节码这层设计是 Java 的命根子。同一份 `.class`,在 Windows 的 HotSpot 上能跑,在 Linux 的 OpenJ9 上也能跑,甚至 Android 早期用的 Dalvik 也是吃这碗饭。跨平台靠的不是源码,是字节码加 JVM 这层抽象。WORA——write once, run anywhere——说的就是这个。

实际项目里你很少手动敲 `javac`。Maven 的 `mvn compile`、Gradle 的 `gradle build`,干的都是同一件事:调 `javac` 把 `src/main/java` 下的源码编译到 `target/classes`。IDE 里点绿色三角,背后也是这套。只不过 IDE 帮你把 classpath、依赖 jar、JVM 参数都拼好了。一旦离开 IDE 就懵的人,多半是没看清这条链。

还有个细节:classpath。`java Hello` 能跑,是因为当前目录默认在 classpath 里。如果你的类带了包名,比如 `com.example.Hello`,那就得写 `java com.example.Hello`,而且目录结构必须匹配。classpath 设错,报 `NoClassDefFoundError` 或 `ClassNotFoundException`,九成是路径问题,不是代码问题。

JVM 拿到字节码后也不是直接解释执行。现代 JVM 会先解释跑一阵,把热点方法用 JIT 编译成本地机器码。所以同一个类,跑得越久往往越快。这也是 Java 在服务端能扛住高并发的原因之一。启动慢、预热长,代价换的是峰值性能。

总结一下这条链:`.java` → `javac` → `.class` → `java` → JVM 加载执行。少一步都跑不起来。下次再有人问“Java 源码怎么运行”,直接让他先看看目录里有没有 `.class` 文件。