InetAddress 提供兩個獲取主機名的方法:getHostName() 返回**創建時使用的名稱**(可能是別名);getCanonicalHostName() 返回**規範主機名**(真實 FQDN)。本文深入對比兩者在不同創建方式下的行為差異、DNS 交互機制及選擇指南。
public String getHostName() // 返回主機別名或創建時的名稱
public String getCanonicalHostName() // 返回規範主機名 (真實 FQDN)
| 創建方式 | getHostName() | getCanonicalHostName() | 是否訪問 DNS |
|---|---|---|---|
getLocalHost() | 本機名 | 本機名 | 否 |
域名 (如 www.ibm.com) | 該域名 (別名) | 視 DNS 配置而定 (可能同別名、可能為真實 FQDN) | getHostName: 否 getCanonicalHostName: 視情況 |
IP 地址 (如 141.146.8.66) | 反解析得到的 FQDN | 同 getHostName() (均為 FQDN) | 是 (反向 DNS PTR 查詢) |
許多網站使用 CNAME 別名 (如 www.oracle.com → bigip-otn-portal.oracle.com):
getHostName() 直接返回構造時傳入的字符串 (www.oracle.com),**零 DNS 開銷**。getCanonicalHostName() 嘗試解析真實 FQDN,可能觸發 DNS 查詢 (視 JVM 緩存/OS 解析器行為)。構造時不解析,首次調用任一方法才發起 PTR 查詢。若 DNS 不允許反解或 IP 無 PTR 記錄,雙雙返回 IP 字符串。
兩者均返回系統配置的主機名,無網路交互。
public class HostNameComparison {
static void print(InetAddress addr, String label) {
System.out.println("通過 " + label + " 創建:");
System.out.println(" 規範主機名: " + addr.getCanonicalHostName());
System.out.println(" 主機別名: " + addr.getHostName());
System.out.println();
}
public static void main(String[] args) throws Exception {
print(InetAddress.getLocalHost(), "getLocalHost()");
print(InetAddress.getByName("www.ibm.com"), "www.ibm.com");
print(InetAddress.getByName("www.126.com"), "www.126.com");
print(InetAddress.getByName("202.108.9.77"), "202.108.9.77 (126.com IP)");
print(InetAddress.getByName("211.100.26.121"), "211.100.26.121 (csdn IP)");
}
}
通過 getLocalHost() 創建:
規範主機名: ComputerName
主機別名: ComputerName
通過 www.ibm.com 創建:
規範主機名: www.ibm.com
主機別名: www.ibm.com
通過 www.126.com 創建:
規範主機名: zz-9-77-a8.bta.net.cn
主機別名: www.126.com
通過 202.108.9.77 創建:
規範主機名: zz-9-77-a8.bta.net.cn
主機別名: zz-9-77-a8.bta.net.cn
通過 211.100.26.121 創建:
規範主機名: 211.100.26.121
主機別名: 211.100.26.121
| 需求 | 推薦方法 | 理由 |
|---|---|---|
| 顯示用戶可識別的域名 (URL 欄風格) | getHostName() | 返回創建時傳入的名稱,零開銷,符合用戶心智 | SSL 證書驗證 / 安全審計 / 真實身份識別 | getCanonicalHostName() | 獲取真實 FQDN,防止別名欺騙 |
| 高性能日誌/監控 (大量調用) | getHostName() | 避免潛在 DNS 查詢延遲 |
| IP 反解析場景 | 任意 (兩者同) | 均觸發 PTR 查詢,結果一致 |
getCanonicalHostName() 可能拋出 SecurityException (安全管理器限制 DNS)。