为什么使用Java 8运行时MulticastSocket.setNetworkInterface()要慢得多?

我正在运行以下程序,与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防火墙,但这没有任何区别.

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

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

任何可能导致此行为的想法或我如何进一步排除故障?

最佳答案
这看起来像ipv6的问题.

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

如果我使用-Djava.net.preferIPv4Stack = true禁用ipv6堆栈,则需要大约100个工厂.

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

转载注明原文:为什么使用Java 8运行时MulticastSocket.setNetworkInterface()要慢得多? - 代码日志