确定一个InetSocketAddress是IPv6还是IPv4

6
我需要有效地确定一个InetSocketAddress是IPv6还是IPv4。我能想到的只有两种方法:使用instanceof运算符或检查getAddress()(应该返回一个byte[])的长度。这两种方法都不太理想(instanceof很慢,而getAddress需要复制数组)。是否有更好的替代方案?

3
根据这篇文章instanceof可能没有你想象的那么慢。个人认为,除非你已经对应用程序进行了分析,并且它报告instanceof占用了> 5%的运行时间,否则我会推迟优化instanceof - Alistair A. Israel
4个回答

5
我认为你不会找到比instanceof更快的方法。在这种特殊情况下,我期望JIT编译器将其优化为加载并比较一对指针;即大约5条机器指令。
但是即使instanceof比我理解的要慢得多,它对应用程序的整体性能影响极小。
我建议你只使用instanceof,并且只在有确凿证据表明存在瓶颈时才对其进行优化;例如,来自在实际工作负载上对应用程序进行分析的证据。

inetSocketAddress.getAddress() instanceof Inet6Address - Sam Ginrich

4

更快的解决方法是比较类型。 Inet4Address和Inet6Address类型是final类型,因此它们不能被子类化。

Inet4Address.class == IPtoCheck.getClass();
Inet6Address.class == IPtoCheck.getClass();

测试显示这比 instanceof 快两倍以上,并且不受比较类型的影响,而 instanceof 在 Inet4 和 Inet6 地址上的性能是不同的。


但是根据这个测试,在Java 8中,instanceof是最快的。我倾向于相信一个可以查看源代码的基准测试,而不是没有引用的基准测试。性能差异太小,不足以成为显著因素,所以我的猜测是Java 8 JIT编译器将使用getClassinstanceof的方法优化为等效的本机代码。请注意,即使一个类不是final,JIT编译器也可以确定它是一个叶子类。如果加载另一个类改变了这个决定,它也可以重新优化。 - Stephen C

1

如果你不喜欢使用instanceof,你可以尝试:

Inet4Address.class.isAssignableFrom(IPtoCheck);
Inet6Address.class.isAssignableFrom(IPtoCheck);

我认为除了使用 instanceof 或上述方法以外,没有更快的解决方案。


1
这会比 instanceof 慢。JIT 编译器无法优化反射类型检查。 - Stephen C

1

与构造带有隐含 DNS 开销的 InetAddress 本身相比,instanceof 的开销(如果有)都是微不足道的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接