4

I am running the following program, which is much slower when I use a Java 8 runtime compared to a Java 7 runtime.

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");
    }
}

When I run this on java 8 it takes about 3500 milliseconds. On Java 7 it takes about 150 milliseconds.

I am using the following java versions:

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)

and

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)

I am on Windows 7, service pack 1, specifics:

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

My machine has 25 different interfaces (a lot of virtual ones), but the operation takes about the same time for each interface.

Some of the calls fail, but even the successful calls are slow. An interesting fact is that the error message on failed operations are different between Java versions:

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)

Running jstack I see the most time spent in the following thread stack:

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)

I have tried disabling all windows firewalls but that made no difference.

The program itself might mot make much sense but I am trying to troubleshoot an issue with a third party platform which runs this kind of code, why rewriting it is not an option.

The problem is reproducable on other workstations in our office.

Any ideas what could cause this behavior or how I could troubleshoot it further?

K Erlandsson
  • 13,408
  • 6
  • 51
  • 67
  • 1
    Are you actually running this with `catch (IOException e) {}` ? Maybe an exception is being thrown and swallowed that would explain the delay? – artbristol Jun 23 '15 at 08:15
  • @artbristol let me rephrase the last comment. I have tried catching and checking the exception. It actually yields different exceptions on Java 7 and java 8. However, the slowness is seen on successful calls as well, not only on the ones yielding error. It is interesting though that exceptions are different, it might be worth looking into. I'll add the details to the question. – K Erlandsson Jun 23 '15 at 08:19
  • 1
    How do you test? Do you consider the *port* need time to be released when you close your program? – chengpohi Jun 23 '15 at 08:20
  • @chengpohi good input. I have tried changing the port between runs with the different versions - no change in behavior. – K Erlandsson Jun 23 '15 at 08:25

1 Answers1

1

This looks like an issue with ipv6.

If I run your program locally this takes 1561 millis to run.

If I disable the ipv6 stack with -Djava.net.preferIPv4Stack=true it takes about 100 mills.

Of note is that with ipv6 enabled this program sees 7 interfaces on my machine but only 4 interfaces when only using ipv4.

K Erlandsson
  • 13,408
  • 6
  • 51
  • 67