在 Java 開發中,獲取網卡的 MAC 地址是常見需求,無論是用於軟體授權綁定、設備識別還是網路診斷。然而,Java 標準庫並未提供直接、跨平台的 API 來取得 MAC 地址。本文將介紹一種在 Windows 環境下透過執行系統命令 ipconfig /all 並解析輸出來獲取 MAC 地址的經典做法,同時探討其局限性與現代替代方案。
以下程式碼示範如何在 Windows 上啟動 ipconfig /all 進程,讀取其標準輸出流,並從包含 "Physical Address" 的行中提取 MAC 地址:
package com.example.network;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class MacAddressUtil {
/**
* 獲取本機第一張網卡的 MAC 地址 (僅限 Windows)
* @return MAC 地址字串,若失敗則返回空字串
*/
public static String getMacAddress() {
String address = "";
String os = System.getProperty("os.name");
System.out.println("作業系統: " + os);
// 僅在 Windows 上嘗試此方法
if (os != null && os.startsWith("Windows")) {
try {
ProcessBuilder pb = new ProcessBuilder("ipconfig", "/all");
Process process = pb.start();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
// 尋找包含實體地址的行
if (line.indexOf("Physical Address") != -1) {
int colonIndex = line.indexOf(":");
if (colonIndex != -1) {
address = line.substring(colonIndex + 1).trim();
break; // 取第一個找到的即可
}
}
}
}
return address;
} catch (IOException e) {
System.err.println("執行 ipconfig 失敗: " + e.getMessage());
}
}
return address;
}
public static void main(String[] args) {
String mac = getMacAddress();
System.out.println("獲取到的 MAC 地址: " + mac);
}
}
Runtime.exec() 更靈活,支援參數列表傳遞,避免命令注入風險。ipconfig /all 輸出格式隨系統語言不同而異(中文為「實體地址」,英文為「Physical Address」),實際部署需處理多語言情況。上述方法強依賴 Windows 命令列,無法在 Linux/macOS 上運作。現代 Java (JDK 9+) 建議使用 java.net.NetworkInterface API 實現跨平台獲取:
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
public static String getMacAddressModern() {
try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface ni = interfaces.nextElement();
// 過濾掉回環、虛擬、未啟用的介面
if (!ni.isLoopback() && ni.isUp() && !ni.isVirtual()) {
byte[] macBytes = ni.getHardwareAddress();
if (macBytes != null) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < macBytes.length; i++) {
sb.append(String.format("%02X%s", macBytes[i], (i < macBytes.length - 1) ? "-" : ""));
}
return sb.toString();
}
}
}
} catch (SocketException e) {
e.printStackTrace();
}
return "";
}
雖然執行系統命令是早期 Java 獲取 MAC 地址的常用手段,但存在平台鎖定、語言敏感、權限需求等缺點。現代專案應優先使用 NetworkInterface API,僅在舊版 JDK 或特殊環境下才考慮命令列備案。開發時請務必處理多網卡、虛擬網卡(如 Docker、VPN)導致的多 MAC 地址場景,根據業務邏輯選擇合適的網卡綁定策略。