Gentle_knife's Studio.

JAVA前置概念小记

Word count: 1.8kReading time: 6 min
2025/07/15
loading

机器码、编译、解释

人有人的语言,人能看得懂的的语言是高级语言(就像脑子认为自己是最重要的器官一样),比如说常见的 Java、C、Python。

机器,也就是 CPU 看得懂的语言是机器码(Machine code),机器码是最底层、最低级的语言。都是 0 和 1,人类读不懂。

机器码是 CPU 直接执行的二进制指令。

在高级语言和机器码之间,还有一些中间表示形式,比如字节码(Bytecode,是虚拟机运行的中间代码)、汇编语言(Assembly,是机器码的符号化表示),以及编译器内部使用的抽象语法树(AST,表示代码的结构化树形表达)。不认识也不要紧,就知道高级和低级中间还有一些语言好了。

把更高级的语言翻译成更低级的语言的过程叫做编译 (Compile)

编译就是把一种程序代码(通常是高级语言)翻译成另一种更接近机器能理解的代码。

刚开始,人们用高级语言写好代码,再用编译器(Compiler)把整个代码编译成机器码,再让 CPU 执行。也就是说,你写好了代码,不能直接让 CPU 执行,必须先生成一份或者多份可执行文件,再让 CPU 执行。也就是说,如果你想对原来的代码进行改动,改动一次就要重新编译一次,再执行。有没有办法让代码执行让 CPU 执行呢?

有的,有的,我们有解释器(Interpreter)。

在程序运行时,逐条读取源码或中间代码,边读边“翻译”边执行的过程叫做解释 (Interpret)

解释的具体表现是,你写好代码,直接运行,就可以看到 CPU 执行后的结果了。这都是解释器的功劳,解释器把源程序代码一行一行的读懂,然后一行一行的执行。

但是,用解释器执行的代码,非常非常非常慢,因为解释器需要先“读懂”再“执行”。相反的是,用编译器执行的代码,执行速度就很快。

有些语言主要通过解释器逐条执行代码(如早期 Python),被称为解释型语言;有些语言主要先编译成机器码再执行(如 C 语言),被称为编译型语言。

平台

由于秦始皇并没有统一计算机,所以想让这些语言在不同的计算机上运行,也是一件很麻烦的事情。解释型的语言只需要有个解释器就行,也就是说有这个语言的环境就可以运行。而编译型的语言则更加麻烦,如果你想让 C 语言在 windows 上执行,你需要把代码最终编译成.exe文件。在 Linux 和 macOS 上,生成的文件格式分别是 ELF 和 Mach-O,文件名可以没有固定后缀。

平台 = 操作系统 + CPU 架构

系统 CPU 平台代称
Windows 10 x86_64 Windows-x64
Linux (Ubuntu) x86_64 Linux-x64
macOS M1 ARM64 macOS-arm64

字节码、JVM

虽然你可以让 C、Go、Rust 等语言在 Windows、Linux、macOS 上分别编译和部署,但每个平台都得各自生成、测试和维护一套二进制,可不是件轻松的事。有没有一种方案,能让我们只编写一次程序,就能用同一份分发包跑在各种操作系统上呢?

那我们用 Python 吧!

可以,但是又出现了一些问题,不同的平台自带的 Python 环境是不同的,比如 Ubuntu 20.04系统自带 Python 3.8;CentOS 7系统自带 Python 2.7,并且官方库里没有Python 3.8,只有 Python 3.6 ,想安装 3.8 只能去第三方仓库。同样的 Python 版本,第三方库的版本也可能不同,而版本不同就意味着有可能报错。

所以当规模庞大的时候,Python 会出现兼容性的问题,除非我们用虚拟环境venv/virtualenvPipenvpoetry)或容器化(Docker)来锁定解释器和依赖。 即便同一台机器上做多项目,也能各自隔离,而不会互相污染或升级冲突。

Java 就是为了解决这两个问题而诞生的。Java 先把代码编译成一种中间语言——字节码,再让不同平台上的 JVM 负责翻译执行。

JVM,全称Java Virtual Machine,即Java虚拟机。它是一个能够执行Java字节码的虚拟机,是Java平台的核心组成部分。JVM负责解释和执行Java程序,屏蔽了底层操作系统和硬件平台的差异,使得Java程序可以在不同的平台上运行。

Java 的字节码格式核心结构在各个版本里是一致的 ,也就是说不管是 Java 6、Java 8 还是 Java 17,它们生成的 .class 文件都是同一种结构。因为结构不变,所以只要 JVM 的版本大于等于字节码的版本,能正常加载。

这样一来,‘写一次,跑多处’变成了可能。

JIT

JVM 的性能常常被认为好,因为它的特性是即时编译(JIT,Just-In-Time 编译),JVM 启动时,会先把 Java 字节码解释执行(速度一般)。运行一段时间后,JVM 会把热点代码(经常执行的部分)编译成和平台一致的机器码,直接运行。这样,Java 程序长时间运行后,速度会越来越快。

JIT 是一种折中方案,先用解释执行启动程序,再动态编译成机器码提速,既保证跨平台又提升性能。
很多现代语言(JavaScript、Java、C#)都采用了这个技术,Python 标准实现没有,但有 PyPy 这种带 JIT 的解释器。

还有一些诸如垃圾回收(GC)机制、多线程和并发优化、平台优化的优点不多赘述。

与之相对应的是提前编译(AOT,Ahead-Of-Time)。传统 AOT(提前编译)方案和纯解释方案,都难以同时兼顾“一次构建,多处运行”与“标准一致性”。

很多现代语言都有 JIT 或类似机制:

语言 是否有 JIT? 备注
Java JVM HotSpot JIT
JavaScript 浏览器的 JS 引擎(V8、SpiderMonkey)都用 JIT
Python (PyPy) PyPy 解释器带 JIT
C#/.NET CLR 也有 JIT
Ruby (JRuby) 基于 JVM
Lua (LuaJIT) 轻量级 JIT 编译器

到这里,我们已经了解了 Java 语言从源码到字节码,再由 JVM 解释/JIT 执行,如何在保证跨平台的同时兼顾性能和生态稳定。Java 程序在控制台或桌面环境下就这样跑通了。但在 Web 场景中,我们常常需要一个专门的‘容器’来接收 HTTP 请求、管理 Web 生命周期、处理并发等——这就是 Tomcat 等 Java Web 服务器的用武之地。

CATALOG
  1. 1. 机器码、编译、解释
  2. 2. 平台
  3. 3. 字节码、JVM
  4. 4. JIT