unresolvedaddressexception 是 java 在 socket 连接前无法解析目标地址为 ip 的异常,主因是 host 字符串含协议头、空格、null 或非法格式,而非网络不通;需清洗输入并显式调用 inetaddress.getbyname 提前校验。

UnresolvedAddressException 是什么错误
它不是网络不通或权限问题,而是 Java 在发起 Socket 连接前,连目标地址都没法解析成 IP —— 比如传了 localhost 却 DNS 不通,或写了 http://example.com:8080 这种带协议头的字符串当 host 用。
常见现象:java.nio.channels.UnresolvedAddressException 直接抛在 SocketChannel.connect()、AsynchronousSocketChannel.connect() 或某些 Netty/OkHttp 底层初始化阶段;堆栈里通常看不到 IO 超时,而是一上来就失败。
哪些地方容易传错地址导致这个异常
核心问题:把「逻辑地址」当「网络地址」用了。Java 的 SocketAddress 子类(比如 InetSocketAddress)要求 host 必须是可解析的域名或合法 IPv4/IPv6 字符串,不接受 URL、带端口的完整地址、空值或纯数字字符串(如 "8.8.8.8:53")。
-
InetSocketAddress构造时传了"https://api.example.com:443"→ 错,协议头必须去掉 - 配置文件读出的 host 字段含前后空格,比如
" example.com "→ DNS 解析失败,触发该异常 - 硬编码用了
"localhost",但容器或 CI 环境里 /etc/hosts 没配,或启用了 IPv6 优先却没开本地 ::1 - 调用
new InetSocketAddress(host, port)时,host是null或空字符串 → 直接炸
怎么安全地构造 InetSocketAddress
别信输入源,先清洗再解析。尤其在微服务间地址由配置中心下发、或 CLI 参数传入时,必须做防御性处理。
立即学习“Java免费学习笔记(深入)”;
- 用
host.trim()去空格,再判断host.isEmpty() - 避免直接传用户输入给
InetSocketAddress;优先走InetAddress.getByName(host)显式捕获UnknownHostException,提前暴露问题 - 如果允许使用本地回环,显式写
"127.0.0.1"或"::1",比依赖"localhost"更可控 - 注意 Android 或某些受限 JVM 上,
getByName可能被沙箱拦截,此时需预置 IP 或降级到直连
示例:
String rawHost = config.getString("target.host").trim();
if (rawHost.isEmpty()) {
throw new IllegalArgumentException("host cannot be empty");
}
InetAddress addr = InetAddress.getByName(rawHost); // 这里会抛 UnknownHostException,比 connect() 时更早发现
InetSocketAddress socketAddr = new InetSocketAddress(addr, port);
Netty 和 OkHttp 里的表现差异
它们都封装了底层 Socket,但异常透出时机和包装方式不同,容易误判根源。
- Netty 的
Bootstrap.connect()默认异步,异常可能出现在ChannelFuture.cause()里,类型是java.nio.channels.UnresolvedAddressException,但外层常被包成java.nio.channels.ClosedChannelException或静默吞掉 —— 要开logger.setLevel(DEBUG)看 Netty 的DefaultChannelPipeline初始化日志 - OkHttp 3.14+ 对
http://开头的 URL 会自动提取 host,但若你手动构造Address并传入Dns实现,仍可能因 Dns.resolve() 返回空列表而最终抛此异常;注意它的Dns.SYSTEM在某些 Android 版本上会跳过 hosts 文件 - Spring Boot 的
@Value("${remote.host}")注入后未 trim,配合RestTemplate+HttpComponentsClientHttpRequestFactory,会在连接池创建时集中爆发该异常,而不是每次请求
复杂点在于:它看起来像网络问题,实际卡在 JVM 启动后的第一个 DNS 查询环节。一旦发生,整个客户端初始化就失败,且不会重试 —— 很多人都在 retry 逻辑里加了超时,却忘了最开始连地址都解析不了。










