CPU 序列号是什么?
我们需要明确一个非常重要的概念:现代 CPU 并没有一个像硬盘序列号那样全球唯一的、固化的“序列号”。

我们通常所说的“CPU 序列号”其实是指 CPU 的一个全局唯一标识符,这个 ID 主要来源于 CPU 的 UUID (Universally Unique Identifier),这个 UUID 是在 CPU 制造时被写入到一个特殊寄存器中的,理论上保证全球唯一。
对于 x86 架构的 CPU(Intel, AMD),这个信息可以通过读取 /proc/cpuinfo 文件中的 cpuid 字段来获取,这个 cpuid 值就是 CPU 的 UUID。
通过读取 /proc/cpuinfo (最常用、最可靠)
这是在 Linux 系统上获取 CPU 信息最标准、最可靠的方法。/proc/cpuinfo 是一个虚拟文件系统,它包含了 CPU 的详细信息。
步骤 1:在 Shell 中查看 CPU 信息
打开终端,执行以下命令:

cat /proc/cpuinfo
你会看到类似下面的输出(以一个 Intel CPU 为例):
processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 79 model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz stepping : 3 microcode : 0xba cpu MHz : 2095.438 cache size : 8192 KB physical id : 0 siblings : 8 core id : 0 cpu cores : 4 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 22 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm mpx avx512f avx512dq rdseed adx smap clflushopt clwb intel_pt avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit srbds mmio_stale_data retbleed bogomips : 4390.40 clflush size : 64 cache_alignment : 64 address sizes : 39 bits physical, 48 bits virtual power management:
注意:如果你有多个 CPU 核心,这个文件会包含所有核心的信息,每个核心的信息块之间会有一个空行,我们需要从其中任意一个核心的信息块里提取 cpuid。
步骤 2:在 Java 中实现
Java 代码的核心思路是:
- 使用
Runtime.exec()或ProcessBuilder执行cat /proc/cpuinfo命令。 - 读取命令的输出流。
- 解析输出流的内容,找到
cpuid这一行的值。 - 关闭所有流以避免资源泄漏。
下面是完整的 Java 代码示例:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class CpuSerialReader {
public static void main(String[] args) {
try {
// 调用系统命令读取 /proc/cpuinfo
Process process = Runtime.getRuntime().exec("cat /proc/cpuinfo");
// 使用 BufferedReader 读取命令的输出
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
// 逐行读取
while ((line = reader.readLine()) != null) {
// 查找包含 "cpuid" 的行
if (line.contains("cpuid")) {
// cpuid 的格式通常是 "cpuid : XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
String[] parts = line.split(":");
if (parts.length == 2) {
String cpuId = parts[1].trim();
System.out.println("CPU ID (UUID): " + cpuId);
}
break; // 找到后就可以退出了
}
}
// 等待命令执行完毕,并检查返回码
int exitCode = process.waitFor();
if (exitCode != 0) {
System.err.println("Command execution failed with exit code: " + exitCode);
}
reader.close();
process.destroy();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
代码解释:
Runtime.getRuntime().exec("cat /proc/cpuinfo"): 启动一个新进程来执行cat命令。process.getInputStream(): 获取这个进程的标准输出流,也就是cat命令打印到控制台的内容。BufferedReader: 高效地读取流中的内容。line.contains("cpuid"): 判断当前行是否包含我们需要的标识。line.split(":"): 用冒号分割字符串,得到键和值。parts[1].trim(): 获取冒号后面的部分,并去除首尾空格。process.waitFor(): 阻塞当前线程,直到外部进程执行完毕,这是一个好习惯,可以避免僵尸进程。
使用 dmidecode 命令 (需要 root 权限)
dmidecode 是一个可以读取计算机 DMI (SMBIOS) 表信息的工具,这个表包含了硬件的详细信息,其中也包括处理器的序列号,这个命令通常需要 root 权限才能执行。
步骤 1:在 Shell 中查看
# 需要 sudo 权限 sudo dmidecode -t processor
输出会类似这样:
# dmidecode 3.2
Getting SMBIOS data from sysfs.
SMBIOS 3.0.0 present.
Handle 0x0004, DMI type 4, 52 bytes
Processor Information
Socket Designation: CPU 1
Type: Central Processor
Family: Core i7
Manufacturer: Intel
ID: BFEBFBFF000906EA <-- 这就是 CPU ID
Signature: Type 0, Family 6, Model 79, Stepping 3
Version: Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz
Voltage: 1.3 V
External Clock: 100 MHz
Max Speed: 4000 MHz
Current Speed: 2100 MHz
Status: Populated, Enabled
Upgrade: None
L1 Cache Handle: 0x0005
L2 Cache Handle: 0x0006
L3 Cache Handle: 0x0007
Serial Number: To Be Filled By O.E.M. <-- 通常这里是空的
Asset Tag: To Be Filled By O.E.M.
Part Number: To Be Filled By O.E.M.
Core Count: 4
Core Enabled: 4
Thread Count: 8
Characteristics: 64-bit capable, Multi-Core, HTT, ECC
这里的 ID 字段 BFEBFBFF000906EA CPU 的 ID。
步骤 2:在 Java 中实现
Java 代码逻辑与第一种方法类似,只是执行的命令和解析的行不同。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class DmidecodeCpuReader {
public static void main(String[] args) {
try {
// 注意:需要 root 权限,所以最好用 sudo 来运行 Java 程序
// sudo java DmidecodeCpuReader
Process process = Runtime.getRuntime().exec("dmidecode -t processor");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
// 查找包含 "ID:" 的行
if (line.trim().startsWith("ID:")) {
// 格式 "ID: BFEBFBFF000906EA"
String cpuId = line.split(":", 2)[1].trim();
System.out.println("CPU ID (from dmidecode): " + cpuId);
break;
}
}
int exitCode = process.waitFor();
if (exitCode != 0) {
System.err.println("Command execution failed. Make sure dmidecode is installed and you have sudo privileges.");
System.err.println("Exit code: " + exitCode);
}
reader.close();
process.destroy();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
重要注意事项和最佳实践
-
权限问题:
- 方法一 (
/proc/cpuinfo) 任何普通用户都有读取权限,是首选。 - 方法二 (
dmidecode) 需要root权限,在生产环境中使用会增加安全风险,并且可能因为权限问题失败。
- 方法一 (
-
跨平台问题:
- 这两种方法都仅适用于 Linux 系统,如果你的 Java 程序需要跨平台运行(Windows, macOS),你需要为不同操作系统编写不同的逻辑。
- 在 Windows 上,可以通过
wmic cpu get ProcessorId或读取注册表。 - 在 macOS 上,可以通过
system_profiler SPHardwareDataType | grep "Processor Name"或ioreg -l来获取。
-
虚拟化环境:
- 在虚拟机(VMware, VirtualBox, KVM 等)中,
/proc/cpuinfo和dmidecode返回的可能是虚拟宿主机的信息,而不是物理机的,如果你想获取物理机的信息,需要宿主机提供特殊的机制(VMware 的vmware-toolbox-cmd)。
- 在虚拟机(VMware, VirtualBox, KVM 等)中,
-
健壮性:
- 总是要检查命令的返回值 (
process.waitFor()),如果命令执行失败(dmidecode未安装),程序可以做出相应处理,而不是直接崩溃。 - 使用
try-with-resources语句可以更优雅地管理流资源,避免忘记关闭InputStreamReader和BufferedReader。
// 使用 try-with-resources 的改进版 try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { // ... 读取逻辑 ... } catch (IOException | InterruptedException e) { e.printStackTrace(); } - 总是要检查命令的返回值 (
| 方法 | 优点 | 缺点 | 推荐度 |
|---|---|---|---|
读取 /proc/cpuinfo |
无需 root 权限,简单可靠,是 Linux 标准做法 | 仅限 Linux | ⭐⭐⭐⭐⭐ |
使用 dmidecode |
信息更丰富(可能包含其他硬件ID) | 需要 root 权限,有安全风险,可能失败 | ⭐⭐ |
对于在 Linux 环境下使用 Java 获取 CPU 序列号,强烈推荐使用第一种方法,即读取 /proc/cpuinfo 文件,它是最稳定、最安全、也是最符合 Linux 设计哲学的方式。
