在现代 linux 系统管理中,swap(交换空间)是一个虽然“古老”却依然至关重要的概念。即使在内存价格低廉、服务器动辄配备数十甚至上百 gb 内存的今天,合理配置和管理 swap 仍然是保障系统稳定性和性能的关键环节。本文将带你深入理解 linux swap 的工作原理、创建方法、动态调整技巧,并结合 java 应用场景,提供实用的代码示例和性能优化建议。
什么是 swap?
swap 是 linux 系统中用于扩展物理内存的一种机制。当系统的物理内存(ram)不足时,内核会将一部分暂时不用的内存页(pages)写入到磁盘上的 swap 区域,从而腾出物理内存供活跃进程使用。这个过程称为“换出”(swap out);当这些数据再次被访问时,系统又会将其从磁盘读回内存,称为“换入”(swap in)。
注意:swap 并非 ram 的替代品,而是其补充。频繁的 swap 操作会导致严重的性能下降,因为磁盘 i/o 速度远低于内存访问速度。
swap 可以是:
- 一个专用的磁盘分区(传统方式)
- 一个普通文件(现代常用方式)
- 多个 swap 分区或文件组成的集合
swap 工作原理图解

上图展示了 swap 在内存压力下的基本工作流程。内核通过页面置换算法(如 lru)选择哪些页面应该被换出,以最小化对系统性能的影响。
查看当前 swap 状态
在进行任何操作之前,首先需要了解当前系统的 swap 配置情况。linux 提供了多种命令行工具来查看 swap 使用状态。
使用free命令
free -h
输出示例:
total used free shared buff/cache available mem: 7.7g 2.1g 3.2g 245m 2.4g 5.1g swap: 2.0g 0b 2.0g
这里的 -h 参数表示“human-readable”,即以人类可读的方式显示大小(如 g、m)。
使用swapon命令
swapon --show
输出示例:
name type size used prio /dev/sda5 partition 2g 0b -2
该命令列出所有激活的 swap 设备及其类型、大小、已使用量和优先级。
查看/proc/swaps
cat /proc/swaps
这是内核维护的 swap 信息文件,内容与 swapon --show 类似。
创建 swap 文件(推荐方式)
相比传统的 swap 分区,使用文件作为 swap 更加灵活,特别是在云服务器或虚拟机环境中,无需重新分区即可动态调整大小。
步骤一:创建空文件
使用 fallocate 或 dd 创建指定大小的文件。
方法 1:使用fallocate(快速)
sudo fallocate -l 2g /swapfile
✅ 优点:瞬间完成,不实际写入磁盘数据。
❌ 缺点:某些文件系统(如 ext3)或旧版本内核可能不支持。
方法 2:使用dd(兼容性好)
sudo dd if=/dev/zero of=/swapfile bs=1m count=2048
解释:
if=/dev/zero:输入文件为零设备of=/swapfile:输出文件路径bs=1m:块大小为 1mbcount=2048:复制 2048 个块,总计 2gb
此方法较慢,因为它会实际写入零值填充整个文件。
步骤二:设置权限
出于安全考虑,swap 文件应仅对 root 可读写:
sudo chmod 600 /swapfile
步骤三:格式化为 swap
sudo mkswap /swapfile
输出示例:
setting up swapspace version 1, size = 2 gib (2147479552 bytes) no label, uuid=abcd1234-ef56-7890-abcd-ef1234567890
步骤四:启用 swap
sudo swapon /swapfile
立即生效,无需重启。
步骤五:设置开机自动挂载
编辑 /etc/fstab 文件,在末尾添加一行:
/swapfile none swap sw 0 0
保存后,系统将在每次启动时自动启用该 swap 文件。
调整现有 swap 大小
有时我们需要扩大或缩小现有的 swap 空间。以下是安全调整 swap 文件大小的步骤。
扩大 swap 文件
假设我们要将 /swapfile 从 2gb 扩展到 4gb:
# 1. 关闭当前 swap sudo swapoff /swapfile # 2. 删除旧文件 sudo rm /swapfile # 3. 创建新的更大文件 sudo fallocate -l 4g /swapfile # 4. 设置权限 sudo chmod 600 /swapfile # 5. 格式化 sudo mkswap /swapfile # 6. 重新启用 sudo swapon /swapfile # 7. 验证 free -h
小贴士:如果你不想删除原文件,也可以直接使用 truncate 命令扩容:
sudo truncate -s 4g /swapfile sudo mkswap /swapfile sudo swapon /swapfile
缩小 swap 文件
缩小 swap 文件风险较高,必须确保缩小后的空间仍能满足当前内存需求。
# 1. 关闭 swap sudo swapoff /swapfile # 2. 重建较小的文件(例如 1gb) sudo dd if=/dev/zero of=/swapfile bs=1m count=1024 # 3. 设置权限 sudo chmod 600 /swapfile # 4. 格式化 sudo mkswap /swapfile # 5. 启用 sudo swapon /swapfile
警告:缩小 swap 文件前,请确保系统有足够的物理内存,否则可能导致 oom(out of memory)错误。
swap 优先级与多个 swap 设备
linux 支持同时使用多个 swap 设备(分区或文件),并通过优先级(priority)决定使用顺序。优先级数值越大,越先被使用。
查看优先级
swapon --show
输出可能如下:
name type size used prio /swapfile1 file 2g 0b -2 /swapfile2 file 1g 0b -1
这里 /swapfile2 优先级更高(-1 > -2),会被优先使用。
设置优先级
在启用 swap 时指定优先级:
sudo swapon -p 10 /swapfile
或者在 /etc/fstab 中设置:
/swapfile none swap sw,pri=10 0 0
实战建议:将高速 ssd 上的 swap 文件设置为高优先级,低速 hdd 上的设置为低优先级,可提升整体性能。
动态管理 swap:启用与禁用
在运维过程中,有时需要临时关闭或开启某个 swap 设备。
禁用单个 swap
sudo swapoff /swapfile
禁用所有 swap
sudo swapoff -a
警告:在物理内存不足的情况下禁用所有 swap 可能导致系统崩溃或进程被 oom killer 杀死。
启用所有在 fstab 中定义的 swap
sudo swapon -a
这通常在系统启动时由 init 系统自动执行。
监控 swap 使用情况
持续监控 swap 使用有助于及时发现内存瓶颈。
使用vmstat
vmstat 1 5
每秒输出一次,共5次。关注 si(swap in)和 so(swap out)列:
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 102400 123456 78900 456789 0 0 12 34 100 200 10 5 85 0 0
若 si 和 so 持续大于 0,说明系统正在频繁换页,可能存在内存压力。
使用sar(需安装 sysstat)
sar -w 1 5
显示 swap 活动统计:
linux 5.4.0-xx-generic (hostname) 04/01/2025 _x86_64_ (4 cpu) 03:00:01 pm pswpin/s pswpout/s 03:00:02 pm 0.00 0.00 03:00:03 pm 0.00 0.00
pswpin/s:每秒换入的页面数pswpout/s:每秒换出的页面数
java 应用与 swap:实战代码示例
java 应用,尤其是大型企业应用或微服务,往往消耗大量内存。合理配置 swap 对保障 java 应用稳定性至关重要。
下面是一个模拟内存压力的 java 程序,用于测试系统在内存不足时如何触发 swap。
示例 1:内存消耗器(memoryhog.java)
import java.util.arraylist;
import java.util.list;
import java.util.scanner;
public class memoryhog {
private static list<byte[]> memorychunks = new arraylist<>();
public static void main(string[] args) {
system.out.println("🚀 java memory hog 启动");
system.out.println("本程序将持续分配内存,直到系统内存耗尽或手动停止。");
system.out.println("按回车键开始分配内存...");
new scanner(system.in).nextline();
int chunksizemb = 100; // 每次分配 100mb
long totalallocatedmb = 0;
try {
while (true) {
byte[] chunk = new byte[chunksizemb * 1024 * 1024]; // 分配 100mb
memorychunks.add(chunk); // 保持引用防止 gc 回收
totalallocatedmb += chunksizemb;
system.out.printf("✅ 已分配 %d mb 内存\n", totalallocatedmb);
// 每次分配后稍作休眠,便于观察系统状态
thread.sleep(1000);
}
} catch (outofmemoryerror e) {
system.err.println("💥 发生 outofmemoryerror!");
system.err.println("堆内存已耗尽。系统可能已开始使用 swap 或终止进程。");
e.printstacktrace();
} catch (interruptedexception e) {
thread.currentthread().interrupt();
system.out.println("🛑 程序被中断");
}
}
}编译与运行:
javac memoryhog.java java -xmx4g memoryhog # 限制最大堆为 4gb
在另一个终端窗口中,你可以使用 free -h 或 vmstat 1 实时观察 swap 使用情况。
示例 2:监控 swap 使用的 java 工具类
以下是一个简单的 java 工具类,用于在程序内部监控 swap 使用情况(通过调用系统命令):
import java.io.bufferedreader;
import java.io.inputstreamreader;
public class swapmonitor {
public static void main(string[] args) throws exception {
system.out.println("📊 开始监控 swap 使用情况(每5秒刷新)");
while (true) {
swapinfo info = getswapinfo();
system.out.printf(
"🕒 %s | 总计: %s | 已用: %s | 空闲: %s | 使用率: %.2f%%\n",
java.time.localtime.now(),
formatbytes(info.total),
formatbytes(info.used),
formatbytes(info.free),
info.getusagepercentage()
);
thread.sleep(5000);
}
}
public static swapinfo getswapinfo() throws exception {
process process = runtime.getruntime().exec("free -b");
bufferedreader reader = new bufferedreader(new inputstreamreader(process.getinputstream()));
string line;
while ((line = reader.readline()) != null) {
if (line.startswith("swap:")) {
string[] parts = line.split("\\s+");
long total = long.parselong(parts[1]);
long used = long.parselong(parts[2]);
long free = long.parselong(parts[3]);
return new swapinfo(total, used, free);
}
}
throw new runtimeexception("未找到 swap 信息");
}
private static string formatbytes(long bytes) {
if (bytes < 1024) return bytes + " b";
else if (bytes < 1024 * 1024) return string.format("%.2f kb", bytes / 1024.0);
else if (bytes < 1024 * 1024 * 1024) return string.format("%.2f mb", bytes / (1024.0 * 1024));
else return string.format("%.2f gb", bytes / (1024.0 * 1024 * 1024));
}
static class swapinfo {
final long total, used, free;
swapinfo(long total, long used, long free) {
this.total = total;
this.used = used;
this.free = free;
}
double getusagepercentage() {
if (total == 0) return 0.0;
return (used * 100.0) / total;
}
}
}此工具可用于长期运行的 java 服务中,配合日志系统记录 swap 使用趋势,帮助运维人员提前预警内存瓶颈。
swap 与 jvm 参数调优
jvm 提供了丰富的内存管理参数,合理设置可以减少对 swap 的依赖。
推荐 jvm 启动参数
java \ -xms2g \ # 初始堆大小 -xmx2g \ # 最大堆大小 -xx:maxmetaspacesize=512m \ # 元空间上限 -xx:+useg1gc \ # 使用 g1 垃圾回收器 -xx:maxgcpausemillis=200 \ # 目标最大 gc 暂停时间 -xx:+alwayspretouch \ # 启动时预分配并清零内存页,避免运行时缺页 -xx:+disableexplicitgc \ # 禁用 system.gc() -verbose:gc \ # 输出 gc 日志 -xx:+printgcdetails \ -xx:+printgctimestamps \ -xloggc:/var/log/myapp-gc.log \ -djava.awt.headless=true \ -jar myapp.jar
alwayspretouch 参数特别重要:它强制 jvm 在启动时就触碰(touch)所有堆内存页,促使操作系统立即分配物理内存或 swap 空间,避免在高峰期因缺页中断导致延迟飙升。
swap 对 java 应用性能的影响分析
swap 的使用对 java 应用的性能影响主要体现在以下几个方面:
- gc 暂停时间增加:垃圾回收器需要扫描和移动对象,如果这些对象位于 swap 中,i/o 延迟会导致 gc 暂停时间大幅增加。
- 响应时间不稳定:用户请求处理过程中若触发缺页中断,响应时间可能出现毛刺(spike)。
- 吞吐量下降:频繁的换页操作占用 i/o 带宽,降低整体吞吐能力。

因此,在生产环境中,应尽量避免 java 进程使用 swap。可以通过以下方式实现:
- 为 jvm 分配合理的堆大小(不超过物理内存的 70%)
- 启用
alwayspretouch - 监控 swap 使用率,设置告警阈值(如 > 10%)
- 使用容器化部署时,设置内存限制并禁用 swap(如 docker 的
--memory-swappiness=0)
容器环境中的 swap 管理
在 docker 或 kubernetes 环境中,swap 的行为有所不同。
docker 中控制 swap
docker run \ --memory="2g" \ --memory-swap="2g" \ # 等于内存 => 禁用 swap --memory-swappiness=0 \ # 禁止容器使用 swap my-java-app
--memory-swap:总内存限制(内存 + swap)。设为与--memory相同值即禁用 swap。--memory-swappiness=0:完全禁止使用 swap。
kubernetes 中的资源限制
在 pod 的 yaml 配置中:
apiversion: v1
kind: pod
metadata:
name: java-app
spec:
containers:
- name: app
image: my-java-image
resources:
limits:
memory: "2gi"
requests:
memory: "1.5gi"kubernetes 默认不允许容器使用 swap。若节点启用了 swap,kubelet 会忽略它,除非显式配置 --fail-swap-on=false。
故障排查:swap 导致的问题诊断
当系统变慢或 java 应用出现无响应时,swap 往往是罪魁祸首之一。
诊断步骤:
检查 swap 使用率
free -h
如果 swap 使用率 > 50%,需警惕。
查看换页活动
vmstat 1 5
若 si/so 持续 > 100 kb/s,说明存在频繁换页。
找出占用 swap 的进程
for file in /proc/*/status ; do
awk '/vmswap|name/{printf $2 " " $3}end{ print ""}' $file 2>/dev/null
done | sort -k 2 -n -r | head -10
输出示例:
java 102400 kb mysqld 51200 kb nginx 1024 kb
查看具体进程的内存映射
cat /proc/<pid>/smaps | grep -i swap
可看到哪些内存区域被换出。
最佳实践总结
生产环境建议启用 swap
即使内存充足,也应配置适量 swap(如物理内存的 10%-20%),以防突发内存需求导致 oom。
不要过度依赖 swap
swap 是“安全气囊”,不是“发动机”。频繁使用 swap 表明系统设计或资源配置存在问题。
ssd 上的 swap 性能更好
如果使用 swap,尽量放在 ssd 上,并设置较高优先级。
java 应用应预分配内存
使用 -xx:+alwayspretouch 避免运行时缺页。
监控与告警
部署监控系统(如 prometheus + grafana),对 swap 使用率、换页速率设置告警。
容器环境明确禁用 swap
除非有特殊需求,否则在容器中禁用 swap,确保资源隔离。
定期审查 swap 配置
随着业务增长,定期评估是否需要调整 swap 大小或升级物理内存。
附录:一键 swap 管理脚本
以下是一个 bash 脚本,用于快速创建、扩展或删除 swap 文件:
#!/bin/bash
# swap-manager.sh - 简易 swap 管理脚本
# 用法:./swap-manager.sh create 2g # 创建 2gb swap
# ./swap-manager.sh resize 4g # 调整为 4gb
# ./swap-manager.sh remove # 删除 swap
swapfile="/swapfile"
fstab="/etc/fstab"
case "$1" in
create)
size="$2"
if [ -z "$size" ]; then
echo "❌ 请指定大小,如:2g"
exit 1
fi
echo "🔧 正在创建 $size 的 swap 文件..."
sudo fallocate -l "$size" "$swapfile" || {
echo "⚠️ fallocate 失败,尝试使用 dd..."
sudo dd if=/dev/zero of="$swapfile" bs=1m count=$(echo "$size" | sed 's/g/*1024/' | bc)
}
sudo chmod 600 "$swapfile"
sudo mkswap "$swapfile"
sudo swapon "$swapfile"
# 添加到 fstab
if ! grep -q "$swapfile" "$fstab"; then
echo "$swapfile none swap sw 0 0" | sudo tee -a "$fstab" > /dev/null
fi
echo "✅ swap 已启用:$(free -h | grep swap)"
;;
resize)
size="$2"
if [ -z "$size" ]; then
echo "❌ 请指定新大小,如:4g"
exit 1
fi
echo "🔄 正在调整 swap 大小至 $size..."
sudo swapoff "$swapfile"
sudo rm "$swapfile"
sudo fallocate -l "$size" "$swapfile" || {
sudo dd if=/dev/zero of="$swapfile" bs=1m count=$(echo "$size" | sed 's/g/*1024/' | bc)
}
sudo chmod 600 "$swapfile"
sudo mkswap "$swapfile"
sudo swapon "$swapfile"
echo "✅ swap 已调整:$(free -h | grep swap)"
;;
remove)
echo "🗑️ 正在移除 swap..."
sudo swapoff "$swapfile"
sudo rm "$swapfile"
# 从 fstab 中删除
sudo sed -i "\|^$swapfile|d" "$fstab"
echo "✅ swap 已移除"
;;
*)
echo "用法:$0 {create|resize|remove} [size]"
echo "示例:"
echo " $0 create 2g"
echo " $0 resize 4g"
echo " $0 remove"
;;
esac保存为 swap-manager.sh,赋予执行权限:
chmod +x swap-manager.sh
即可方便地管理 swap 文件。
结语
swap 是 linux 系统内存管理的重要组成部分,尤其在运行内存密集型 java 应用时,合理配置 swap 能显著提升系统稳定性和容错能力。通过本文的学习,你已经掌握了 swap 的创建、调整、监控和优化方法,并能结合 java 应用进行实战调优。
记住:swap 不是性能的敌人,滥用才是。 正确理解和使用 swap,让它成为你系统架构中的“守护者”,而非“拖油瓶”。
以上就是linux swap交换分区的创建与调整方案的详细内容,更多关于linux swap交换分区创建与调整的资料请关注代码网其它相关文章!
发表评论