InetAddress.getHostName() 根據對象創建方式呈現三種截然不同的行為:直接返回、零開銷;觸發反向 DNS 查詢、有延遲;返回 IP 字符串。本文詳細解析三種模式、耗時對比及實務建議。
| 創建方式 | 代碼示例 | getHostName() 行為 | 耗時 | DNS 交互 |
|---|---|---|---|---|
| getLocalHost() | InetAddress.getLocalHost() | 返回本機名 | ~0ms | 無 |
| 域名創建 | InetAddress.getByName("www.oracle.com") | 直接返回構造時的域名 | ~0ms | 無 (構造時已解析) |
| IP 地址創建 | InetAddress.getByName("141.146.8.66") | 觸發反向 DNS (PTR) 查詢,返回 FQDN | 首次 ~幾十~百 ms | 是 (首次調用時) |
public class HostNameTiming {
public static void main(String[] args) throws Exception {
// 1. 本機名
InetAddress local = InetAddress.getLocalHost();
System.out.println("本機名: " + local.getHostName());
// 2. 域名創建 -> 直接返回
InetAddress byName = InetAddress.getByName("www.oracle.com");
long t1 = System.currentTimeMillis();
System.out.println("直接得域名: " + byName.getHostName() + " 耗時: " + (System.currentTimeMillis()-t1) + "ms");
// 3. IP 創建 -> 反向 DNS
InetAddress byIp = InetAddress.getByName("141.146.8.66");
System.out.println("創建時: " + byIp); // 僅顯示 IP
long t2 = System.currentTimeMillis();
String fqdn = byIp.getHostName();
System.out.println("反向DNS得: " + fqdn + " 耗時: " + (System.currentTimeMillis()-t2) + "ms");
System.out.println("再次調用: " + byIp); // 顯示 FQDN/IP
}
}
本機名: ComputerName
直接得域名: www.oracle.com 耗時: 0ms
創建時: /141.146.8.66
反向DNS得: bigip-otn-portal.oracle.com 耗時: 92ms
再次調用: bigip-otn-portal.oracle.com/141.146.8.66
關鍵觀察:
- 域名創建模式:
getHostName()**極快 (0ms)**,因構造器getByName()已完成正向解析並緩存域名。- IP 創建模式:首次調用 **顯著延遲 (92ms)**,發起 PTR 查詢;後續調用命中緩存極快。
- 同一 IP 可能對應多個域名 (CNAME 鏈),PTR 返回的是區域配置的規範名,不一定是你熟知的公開域名 (如
bigip-otn-portal.oracle.comvswww.oracle.com)。
www.oracle.com 是公開別名 (CNAME),真實規範名可能是內部負載均衡器主機名 bigip-otn-portal.oracle.com。兩者均可訪問服務,但語義不同:
getHostName() 獲取顯示名零開銷。networkaddress.cache.ttl) 控制 PTR 結果存活時間,見「DNS 緩存」章節。