【问题标题】:Why is MulticastSocket.setNetworkInterface() much slower using Java 8 runtime?为什么 MulticastSocket.setNetworkInterface() 使用 Java 8 运行时要慢得多?
【发布时间】:2015-09-08 22:17:08
【问题描述】:

我正在运行以下程序,与 Java 7 运行时相比,我使用 Java 8 运行时要慢得多。

public class MulticastTest {

    public static void main(String args[]) throws Exception {
        long start = System.nanoTime();
        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
        MulticastSocket multicastSocket = new MulticastSocket(6665);
        while (networkInterfaces.hasMoreElements()) {
            NetworkInterface iface = networkInterfaces.nextElement();
            try {
                multicastSocket.setNetworkInterface(iface);
            } catch (IOException e) {
            }
        }
        long durationMillis = (System.nanoTime() - start) / 1000000;
        System.out.println("Took " + durationMillis + " millis");
    }
}

当我在 java 8 上运行它时,大约需要 3500 毫秒。在 Java 7 上大约需要 150 毫秒。

我正在使用以下 java 版本:

java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)

我使用的是 Windows 7,Service Pack 1,具体说明:

OS Name:                   Microsoft Windows 7 Professional
OS Version:                6.1.7601 Service Pack 1 Build 7601

我的机器有 25 个不同的接口(很多虚拟接口),但是每个接口的操作时间都差不多。

有些调用失败,但即使成功调用也很慢。一个有趣的事实是,失败操作的错误消息在 Java 版本之间是不同的:

Java 7:

java.net.SocketException: An invalid argument was supplied
        at java.net.TwoStacksPlainDatagramSocketImpl.socketNativeSetOption(Native Method)
        at java.net.TwoStacksPlainDatagramSocketImpl.socketSetOption(TwoStacksPlainDatagramSocketImpl.java:145)
        at java.net.AbstractPlainDatagramSocketImpl.setOption(AbstractPlainDatagramSocketImpl.java:309)
        at java.net.MulticastSocket.setNetworkInterface(MulticastSocket.java:550)

Java 8:

java.net.SocketException: bad argument for IP_MULTICAST_IF2: No IP addresses bound to interface
        at java.net.TwoStacksPlainDatagramSocketImpl.socketNativeSetOption(Native Method)
        at java.net.TwoStacksPlainDatagramSocketImpl.socketSetOption(Unknown Source)
        at java.net.AbstractPlainDatagramSocketImpl.setOption(Unknown Source)
        at java.net.MulticastSocket.setNetworkInterface(Unknown Source)

运行jstack我看到在以下线程堆栈中花费的时间最多:

main" #1 prio=5 os_prio=0 tid=0x0000000002248000 nid=0x1554 runnable [0x00000000026da000]
  java.lang.Thread.State: RUNNABLE
   at java.net.TwoStacksPlainDatagramSocketImpl.socketNativeSetOption(Native Method)
   at java.net.TwoStacksPlainDatagramSocketImpl.socketSetOption(TwoStacksPlainDatagramSocketImpl.java:146)
   at java.net.AbstractPlainDatagramSocketImpl.setOption(AbstractPlainDatagramSocketImpl.java:310)
   at java.net.MulticastSocket.setNetworkInterface(MulticastSocket.java:554)

我尝试禁用所有 Windows 防火墙,但没有任何区别。

该程序本身可能没有多大意义,但我正在尝试解决运行此类代码的第三方平台的问题,为什么重写它不是一种选择。

这个问题可以在我们办公室的其他工作站上重现。

有什么可能导致这种行为的想法,或者我可以如何进一步排除故障?

【问题讨论】:

  • 你真的用catch (IOException e) {} 运行这个吗?也许正在抛出并吞下一个异常来解释延迟?
  • @artbristol 让我改写最后一条评论。我试过捕捉和检查异常。它实际上在 Java 7 和 Java 8 上产生了不同的异常。但是,在成功调用时也会看到缓慢,而不仅仅是在产生错误的调用上。有趣的是,尽管例外情况不同,但可能值得研究。我将在问题中添加详细信息。
  • 你如何测试?你认为关闭程序时端口需要时间释放吗?
  • @chengpohi 很好的输入。我尝试在不同版本的运行之间更改端口 - 行为没有变化。

标签: java multicast multicastsocket


【解决方案1】:

这看起来像是 ipv6 的问题。

如果我在本地运行你的程序,这需要 1561 毫秒才能运行。

如果我使用 -Djava.net.preferIPv4Stack=true 禁用 ipv6 堆栈,大约需要 100 次。

值得注意的是,启用 ipv6 后,此程序在我的机器上看到 7 个接口,但仅使用 ipv4 时只有 4 个接口。

【讨论】:

    猜你喜欢
    • 2015-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 2017-08-25
    • 2011-04-29
    • 1970-01-01
    相关资源
    最近更新 更多