# HG changeset patch # User redestad # Date 1562326829 -7200 # Node ID d01b345865d78d29f65d958bba5521bdf5e21282 # Parent cf5a438b3c41aa4c742a4456a9c48ecbb6dcf90e 8225239: Refactor NetworkInterface lookups Reviewed-by: michaelm, dfuchs, chegar diff -r cf5a438b3c41 -r d01b345865d7 src/java.base/share/classes/java/net/Inet6AddressImpl.java --- a/src/java.base/share/classes/java/net/Inet6AddressImpl.java Fri Jul 05 12:55:54 2019 +0300 +++ b/src/java.base/share/classes/java/net/Inet6AddressImpl.java Fri Jul 05 13:40:29 2019 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package java.net; import java.io.IOException; + +import static java.net.InetAddress.IPv6; import static java.net.InetAddress.PREFER_IPV6_VALUE; import static java.net.InetAddress.PREFER_SYSTEM_VALUE; @@ -70,7 +72,7 @@ * stack system). */ java.util.Enumeration it = netif.getInetAddresses(); - InetAddress inetaddr = null; + InetAddress inetaddr; while (it.hasMoreElements()) { inetaddr = it.nextElement(); if (inetaddr.getClass().isInstance(addr)) { @@ -110,20 +112,23 @@ boolean preferIPv6Address = InetAddress.preferIPv6Address == PREFER_IPV6_VALUE || InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE; - InetAddress loopback4 = (new Inet4AddressImpl()).loopbackAddress(); - InetAddress loopback6 = new Inet6Address("localhost", - new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}); - // Order the candidate addresses by preference. - InetAddress[] addresses = preferIPv6Address - ? new InetAddress[] {loopback6, loopback4} - : new InetAddress[] {loopback4, loopback6}; - // In case of failure, default to the preferred address. - loopbackAddress = addresses[0]; - // Pick the first candidate address that actually exists. - for (InetAddress address : addresses) { + + for (int i = 0; i < 2; i++) { + InetAddress address; + // Order the candidate addresses by preference. + if (i == (preferIPv6Address ? 0 : 1)) { + address = new Inet6Address("localhost", + new byte[]{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}); + } else { + address = new Inet4Address("localhost", new byte[]{ 0x7f,0x00,0x00,0x01 }); + } + if (i == 0) { + // In case of failure, default to the preferred address. + loopbackAddress = address; + } try { - if (NetworkInterface.getByInetAddress(address) == null) { + if (!NetworkInterface.isBoundInetAddress(address)) { continue; } } catch (SocketException e) { diff -r cf5a438b3c41 -r d01b345865d7 src/java.base/share/classes/java/net/InetAddress.java --- a/src/java.base/share/classes/java/net/InetAddress.java Fri Jul 05 12:55:54 2019 +0300 +++ b/src/java.base/share/classes/java/net/InetAddress.java Fri Jul 05 13:40:29 2019 +0200 @@ -290,7 +290,7 @@ } /* Used to store the name service provider */ - private static transient NameService nameService = null; + private static transient NameService nameService; /** * Used to store the best available hostname. @@ -305,8 +305,7 @@ * Load net library into runtime, and perform initializations. */ static { - String str = java.security.AccessController.doPrivileged( - new GetPropertyAction("java.net.preferIPv6Addresses")); + String str = GetPropertyAction.privilegedGetProperty("java.net.preferIPv6Addresses"); if (str == null) { preferIPv6Address = PREFER_IPV4_VALUE; } else if (str.equalsIgnoreCase("true")) { diff -r cf5a438b3c41 -r d01b345865d7 src/java.base/share/classes/java/net/NetworkInterface.java --- a/src/java.base/share/classes/java/net/NetworkInterface.java Fri Jul 05 12:55:54 2019 +0300 +++ b/src/java.base/share/classes/java/net/NetworkInterface.java Fri Jul 05 13:40:29 2019 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -321,17 +321,16 @@ if (addr == null) { throw new NullPointerException(); } - if (addr instanceof Inet4Address) { - Inet4Address inet4Address = (Inet4Address) addr; - if (inet4Address.holder.family != InetAddress.IPv4) { + + if (addr.holder.family == InetAddress.IPv4) { + if (!(addr instanceof Inet4Address)) { throw new IllegalArgumentException("invalid family type: " - + inet4Address.holder.family); + + addr.holder.family); } - } else if (addr instanceof Inet6Address) { - Inet6Address inet6Address = (Inet6Address) addr; - if (inet6Address.holder.family != InetAddress.IPv6) { + } else if (addr.holder.family == InetAddress.IPv6) { + if (!(addr instanceof Inet6Address)) { throw new IllegalArgumentException("invalid family type: " - + inet6Address.holder.family); + + addr.holder.family); } } else { throw new IllegalArgumentException("invalid address type: " + addr); @@ -394,6 +393,23 @@ } } + /** + * Checks if the given address is bound to any of the interfaces on this + * machine. + * + * @param addr + * The {@code InetAddress} to search with. + * @return true iff the addr parameter is currently bound to one of + * the interfaces on this machine. + * + * @throws SocketException + * If an I/O error occurs. + */ + /* package-private */ static boolean isBoundInetAddress(InetAddress addr) + throws SocketException { + return boundInetAddress0(addr); + } + private static Enumeration enumerationFromArray(T[] a) { return new Enumeration<>() { int i = 0; @@ -431,6 +447,9 @@ private static native NetworkInterface getByIndex0(int index) throws SocketException; + private static native boolean boundInetAddress0(InetAddress addr) + throws SocketException; + private static native NetworkInterface getByInetAddress0(InetAddress addr) throws SocketException; diff -r cf5a438b3c41 -r d01b345865d7 src/java.base/unix/native/libnet/NetworkInterface.c --- a/src/java.base/unix/native/libnet/NetworkInterface.c Fri Jul 05 12:55:54 2019 +0300 +++ b/src/java.base/unix/native/libnet/NetworkInterface.c Fri Jul 05 13:40:29 2019 +0200 @@ -320,33 +320,9 @@ return obj; } -/* - * Class: java_net_NetworkInterface - * Method: getByInetAddress0 - * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface; - */ -JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0 - (JNIEnv *env, jclass cls, jobject iaObj) -{ - netif *ifs, *curr; - jobject obj = NULL; - jboolean match = JNI_FALSE; - int family = getInetAddress_family(env, iaObj); - JNU_CHECK_EXCEPTION_RETURN(env, NULL); - - if (family == java_net_InetAddress_IPv4) { - family = AF_INET; - } else if (family == java_net_InetAddress_IPv6) { - family = AF_INET6; - } else { - return NULL; // Invalid family - } - ifs = enumInterfaces(env); - if (ifs == NULL) { - return NULL; - } - - curr = ifs; +// Return the interface in ifs that iaObj is bound to, if any - otherwise NULL +static netif* find_bound_interface(JNIEnv *env, netif* ifs, jobject iaObj, int family) { + netif* curr = ifs; while (curr != NULL) { netaddr *addrP = curr->addr; @@ -359,11 +335,10 @@ ((struct sockaddr_in *)addrP->addr)->sin_addr.s_addr); int address2 = getInetAddress_addr(env, iaObj); if ((*env)->ExceptionCheck(env)) { - goto cleanup; + return NULL; } if (address1 == address2) { - match = JNI_TRUE; - break; + return curr; } } else if (family == AF_INET6) { jbyte *bytes = (jbyte *)&( @@ -383,30 +358,117 @@ i++; } if (i >= 16) { - match = JNI_TRUE; - break; + return curr; } } } - if (match) { - break; - } addrP = addrP->next; } - - if (match) { - break; - } curr = curr->next; } + return NULL; +} + +/* + * Class: java_net_NetworkInterface + * Method: boundInetAddress0 + * Signature: (Ljava/net/InetAddress;)boundInetAddress; + */ +JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_boundInetAddress0 + (JNIEnv *env, jclass cls, jobject iaObj) +{ + netif *ifs = NULL; + jboolean bound = JNI_FALSE; + int sock; + + int family = getInetAddress_family(env, iaObj); + JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); + + if (family == java_net_InetAddress_IPv4) { + family = AF_INET; + } else if (family == java_net_InetAddress_IPv6) { + family = AF_INET6; + } else { + return JNI_FALSE; // Invalid family + } + + if (family == AF_INET) { + sock = openSocket(env, AF_INET); + if (sock < 0 && (*env)->ExceptionOccurred(env)) { + return JNI_FALSE; + } + + // enumerate IPv4 addresses + if (sock >= 0) { + ifs = enumIPv4Interfaces(env, sock, ifs); + close(sock); + + if ((*env)->ExceptionOccurred(env)) { + goto cleanup; + } + } + if (find_bound_interface(env, ifs, iaObj, family) != NULL) + bound = JNI_TRUE; + } else if (ipv6_available()) { + // If IPv6 is available then enumerate IPv6 addresses. + // User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true, + // so we have to call ipv6_available() + sock = openSocket(env, AF_INET6); + if (sock < 0) { + return JNI_FALSE; + } + + ifs = enumIPv6Interfaces(env, sock, ifs); + close(sock); + + if ((*env)->ExceptionOccurred(env)) { + goto cleanup; + } + + if (find_bound_interface(env, ifs, iaObj, family) != NULL) + bound = JNI_TRUE; + } + +cleanup: + freeif(ifs); + + return bound; +} + +/* + * Class: java_net_NetworkInterface + * Method: getByInetAddress0 + * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface; + */ +JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0 + (JNIEnv *env, jclass cls, jobject iaObj) +{ + netif *ifs, *curr; + jobject obj = NULL; + int family = getInetAddress_family(env, iaObj); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); + + if (family == java_net_InetAddress_IPv4) { + family = AF_INET; + } else if (family == java_net_InetAddress_IPv6) { + family = AF_INET6; + } else { + return NULL; // Invalid family + } + ifs = enumInterfaces(env); + if (ifs == NULL) { + return NULL; + } + + curr = find_bound_interface(env, ifs, iaObj, family); + // if found create a NetworkInterface - if (match) { + if (curr != NULL) { obj = createNetworkInterface(env, curr); } -cleanup: // release the interface list freeif(ifs); diff -r cf5a438b3c41 -r d01b345865d7 src/java.base/windows/native/libnet/NetworkInterface.c --- a/src/java.base/windows/native/libnet/NetworkInterface.c Fri Jul 05 12:55:54 2019 +0300 +++ b/src/java.base/windows/native/libnet/NetworkInterface.c Fri Jul 05 13:40:29 2019 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include "net_util.h" #include "NetworkInterface.h" +#include "java_net_InetAddress.h" #include "java_net_NetworkInterface.h" /* @@ -347,7 +348,7 @@ /* * Free the interface table and return the interface list */ - if (tableP) { + if (tableP != NULL) { free(tableP); } *netifPP = netifP; @@ -355,24 +356,13 @@ } /* - * Enumerate the IP addresses on an interface using the IP helper library - * routine GetIfAddrTable and matching based on the index name. There are - * more efficient routines but we use GetIfAddrTable because it's avaliable - * on 98 and NT. - * - * Returns the count of addresses, or -1 if error. If no error occurs then - * netaddrPP will return a list of netaddr structures with the IP addresses. + * Enumerate all addresses using the IP helper library */ -int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP) +int lookupIPAddrTable(JNIEnv *env, MIB_IPADDRTABLE **tablePP) { MIB_IPADDRTABLE *tableP; ULONG size; DWORD ret; - DWORD i; - netaddr *netaddrP; - int count = 0; - unsigned long mask; - /* * Use GetIpAddrTable to enumerate the IP Addresses */ @@ -396,7 +386,7 @@ ret = GetIpAddrTable(tableP, &size, FALSE); } if (ret != NO_ERROR) { - if (tableP) { + if (tableP != NULL) { free(tableP); } JNU_ThrowByName(env, "java/lang/Error", @@ -405,16 +395,35 @@ // GetIpAddrTable in pure IPv6 environment return -2; } + *tablePP = tableP; + return 0; +} + +/* + * Enumerate the IP addresses on an interface, given an IP address table + * and matching based on index. + * + * Returns the count of addresses, or -1 if error. If no error occurs then + * netaddrPP will return a list of netaddr structures with the IP addresses. + */ +int enumAddresses_win_ipaddrtable(JNIEnv *env, netif *netifP, netaddr **netaddrPP, MIB_IPADDRTABLE *tableP) +{ + DWORD i; + netaddr *netaddrP; + int count = 0; + unsigned long mask; /* * Iterate through the table to find the addresses with the * matching dwIndex. Ignore 0.0.0.0 addresses. */ + if (tableP == NULL) + return 0; count = 0; netaddrP = NULL; i = 0; - while (idwNumEntries) { + while (i < tableP->dwNumEntries) { if (tableP->table[i].dwIndex == netifP->dwIndex && tableP->table[i].dwAddr != 0) { @@ -437,33 +446,33 @@ case MIB_IF_TYPE_FDDI: case MIB_IF_TYPE_LOOPBACK: case IF_TYPE_IEEE80211: - /** - * Contrary to what it seems to indicate, dwBCastAddr doesn't - * contain the broadcast address but 0 or 1 depending on whether - * the broadcast address should set the bits of the host part - * to 0 or 1. - * Yes, I know it's stupid, but what can I say, it's MSFTs API. - */ - curr->brdcast.sa4.sin_family = AF_INET; - if (tableP->table[i].dwBCastAddr == 1) - curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask) | (0xffffffff ^ tableP->table[i].dwMask); - else - curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask); - mask = ntohl(tableP->table[i].dwMask); - curr->mask = 0; - while (mask) { - mask <<= 1; - curr->mask++; - } - break; + /** + * Contrary to what it seems to indicate, dwBCastAddr doesn't + * contain the broadcast address but 0 or 1 depending on whether + * the broadcast address should set the bits of the host part + * to 0 or 1. + * Yes, I know it's stupid, but what can I say, it's MSFTs API. + */ + curr->brdcast.sa4.sin_family = AF_INET; + if (tableP->table[i].dwBCastAddr == 1) + curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask) | (0xffffffff ^ tableP->table[i].dwMask); + else + curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask); + mask = ntohl(tableP->table[i].dwMask); + curr->mask = 0; + while (mask) { + mask <<= 1; + curr->mask++; + } + break; case MIB_IF_TYPE_PPP: case MIB_IF_TYPE_SLIP: default: - /** - * these don't have broadcast/subnet - */ - curr->mask = -1; - break; + /** + * these don't have broadcast/subnet + */ + curr->mask = -1; + break; } curr->next = netaddrP; @@ -474,10 +483,30 @@ } *netaddrPP = netaddrP; + return count; +} + + +/* + * Enumerate the IP addresses on an interface, using an IP address table + * retrieved using GetIPAddrTable and matching based on index. + * + * Returns the count of addresses, or -1 if error. If no error occurs then + * netaddrPP will return a list of netaddr structures with the IP addresses. + */ +int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP) { + MIB_IPADDRTABLE *tableP; + int count; + int ret = lookupIPAddrTable(env, &tableP); + if (ret < 0) { + return NULL; + } + count = enumAddresses_win_ipaddrtable(env, netifP, netaddrPP, tableP); free(tableP); return count; } + /* * Class: java_net_NetworkInterface * Method: init @@ -758,6 +787,50 @@ return netifObj; } + +/* + * Class: java_net_NetworkInterface + * Method: boundInetAddress0 + * Signature: (Ljava/net/InetAddress;)Z + */ +JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_boundInetAddress0 + (JNIEnv *env, jclass cls, jobject iaObj) +{ + jobject netifObj = NULL; + DWORD i; + + int family = getInetAddress_family(env, iaObj); + JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); + + if (family == java_net_InetAddress_IPv6) { + if (!ipv6_available()) + return JNI_FALSE; + return Java_java_net_NetworkInterface_getByInetAddress0_XP(env, cls, iaObj) != NULL; + } else if (family == java_net_InetAddress_IPv4) { + jint addr = getInetAddress_addr(env, iaObj); + JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); + + jboolean found = JNI_FALSE; + MIB_IPADDRTABLE *tableP; + if (lookupIPAddrTable(env, &tableP) >= 0 && tableP != NULL) { + for (i = 0; i < tableP->dwNumEntries; i++) { + if (tableP->table[i].dwAddr != 0 && + (unsigned long)addr == ntohl(tableP->table[i].dwAddr)) { + found = JNI_TRUE; + break; + } + } + } + if (tableP != NULL) { + free(tableP); + } + return found; + } else { + // Unknown address family + return JNI_FALSE; + } +} + /* * Class: java_net_NetworkInterface * Method: getByInetAddress0 @@ -767,11 +840,11 @@ (JNIEnv *env, jclass cls, jobject iaObj) { netif *ifList, *curr; + MIB_IPADDRTABLE *tableP; jobject netifObj = NULL; jint addr = getInetAddress_addr(env, iaObj); JNU_CHECK_EXCEPTION_RETURN(env, NULL); - // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack if (ipv6_available()) { return Java_java_net_NetworkInterface_getByInetAddress0_XP (env, cls, iaObj); } @@ -785,42 +858,50 @@ * Enumerate the addresses on each interface until we find a * matching address. */ - curr = ifList; - while (curr != NULL) { - int count; - netaddr *addrList; - netaddr *addrP; + tableP = NULL; + if (lookupIPAddrTable(env, &tableP) >= 0) { + curr = ifList; + while (curr != NULL) { + int count; + netaddr *addrList; + netaddr *addrP; + + /* enumerate the addresses on this interface */ + count = enumAddresses_win_ipaddrtable(env, curr, &addrList, tableP); + if (count < 0) { + free_netif(ifList); + free(tableP); + return NULL; + } - /* enumerate the addresses on this interface */ - count = enumAddresses_win(env, curr, &addrList); - if (count < 0) { - free_netif(ifList); - return NULL; - } + /* iterate through each address */ + addrP = addrList; - /* iterate through each address */ - addrP = addrList; + while (addrP != NULL) { + if ((unsigned long)addr == ntohl(addrP->addr.sa4.sin_addr.s_addr)) { + break; + } + addrP = addrP->next; + } - while (addrP != NULL) { - if ((unsigned long)addr == ntohl(addrP->addr.sa4.sin_addr.s_addr)) { + /* + * Address matched so create NetworkInterface for this interface + * and address list. + */ + if (addrP != NULL) { + /* createNetworkInterface will free addrList */ + netifObj = createNetworkInterface(env, curr, count, addrList); break; } - addrP = addrP->next; - } - /* - * Address matched so create NetworkInterface for this interface - * and address list. - */ - if (addrP != NULL) { - /* createNetworkInterface will free addrList */ - netifObj = createNetworkInterface(env, curr, count, addrList); - break; + /* on next interface */ + curr = curr->next; } + } - /* on next interface */ - curr = curr->next; - } + /* release the IP address table */ + if (tableP != NULL) + free(tableP); /* release the interface list */ free_netif(ifList); diff -r cf5a438b3c41 -r d01b345865d7 src/java.base/windows/native/libnet/NetworkInterface_winXP.c --- a/src/java.base/windows/native/libnet/NetworkInterface_winXP.c Fri Jul 05 12:55:54 2019 +0300 +++ b/src/java.base/windows/native/libnet/NetworkInterface_winXP.c Fri Jul 05 13:40:29 2019 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,9 @@ * and getByAddress. */ +extern int enumAddresses_win_ipaddrtable(JNIEnv *env, netif *netifP, netaddr **netaddrPP, MIB_IPADDRTABLE *tableP); extern int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP); +extern int lookupIPAddrTable(JNIEnv *env, MIB_IPADDRTABLE **tablePP); int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP); #ifdef DEBUG @@ -239,6 +241,7 @@ int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP) { DWORD ret; + MIB_IPADDRTABLE *tableP; IP_ADAPTER_ADDRESSES *ptr, *adapters=NULL; ULONG len=ipinflen, count=0; netif *nif=NULL, *dup_nif, *last=NULL, *loopif=NULL, *curr; @@ -271,10 +274,15 @@ // Retrieve IPv4 addresses with the IP Helper API curr = *netifPP; + ret = lookupIPAddrTable(env, &tableP); + if (ret < 0) { + return -1; + } while (curr != NULL) { netaddr *netaddrP; - ret = enumAddresses_win(env, curr, &netaddrP); + ret = enumAddresses_win_ipaddrtable(env, curr, &netaddrP, tableP); if (ret == -1) { + free(tableP); return -1; } else if (ret == -2) { if ((*env)->ExceptionCheck(env)) { @@ -287,7 +295,7 @@ curr = curr->next; } } - + free(tableP); ret = getAdapters (env, &adapters); if (ret != ERROR_SUCCESS) { goto err; diff -r cf5a438b3c41 -r d01b345865d7 test/jdk/java/net/NetworkInterface/NetworkInterfaceRetrievalTests.java --- a/test/jdk/java/net/NetworkInterface/NetworkInterfaceRetrievalTests.java Fri Jul 05 12:55:54 2019 +0300 +++ b/test/jdk/java/net/NetworkInterface/NetworkInterfaceRetrievalTests.java Fri Jul 05 13:40:29 2019 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,17 +23,21 @@ /** * @test - * @bug 8179559 + * @bug 8179559 8225239 */ import java.net.InetAddress; import java.net.NetworkInterface; import java.util.Enumeration; +import java.lang.reflect.Method; public class NetworkInterfaceRetrievalTests { public static void main(String[] args) throws Exception { int checkFailureCount = 0; + Method isBound = NetworkInterface.class.getDeclaredMethod("isBoundInetAddress", InetAddress.class); + isBound.setAccessible(true); + try { Enumeration en = NetworkInterface .getNetworkInterfaces(); @@ -58,6 +62,13 @@ checkFailureCount++; } + // Any bound address should return true when calling isBoundInetAddress + if (!((boolean)isBound.invoke(null, addr))) { + System.out.println("Retreived net if bound addr " + addr + + "NOT shown as bound using NetworkInterface.isBoundAddress " + + "***********"); + checkFailureCount++; + } } } diff -r cf5a438b3c41 -r d01b345865d7 test/micro/org/openjdk/bench/java/net/NetworkInterfaceLookup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/micro/org/openjdk/bench/java/net/NetworkInterfaceLookup.java Fri Jul 05 13:40:29 2019 +0200 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.net; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.lang.reflect.Method; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.util.concurrent.TimeUnit; + +/** + * Assess time to perform native NetworkInterface lookups; uses + * reflection to access both package-private isBoundInetAddress and + * public getByInetAddress (to get comparable numbers) + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +@Fork(2) +@Warmup(iterations = 5, time = 2) +@Measurement(iterations = 10, time = 2) +public class NetworkInterfaceLookup { + + static final InetAddress address = InetAddress.getLoopbackAddress(); + + static final Method isBoundInetAddress_method; + + static final Method getByInetAddress_method; + + static { + Method isBound = null; + Method getByInet = null; + + try { + isBound = NetworkInterface.class.getDeclaredMethod("isBoundInetAddress", InetAddress.class); + isBound.setAccessible(true); + } catch (Exception e) { + System.out.println("NetworkInterface.isBoundInetAddress not found"); + } + + try { + getByInet = NetworkInterface.class.getDeclaredMethod("getByInetAddress", InetAddress.class); + } catch (Exception e) { + System.out.println("NetworkInterface.getByInetAddress not found"); + } + isBoundInetAddress_method = isBound; + getByInetAddress_method = getByInet; + } + + @Benchmark + public boolean bound() throws Exception { + return (boolean)isBoundInetAddress_method.invoke(null, address); + } + + @Benchmark + public NetworkInterface getByInetAddress() throws Exception { + return (NetworkInterface)getByInetAddress_method.invoke(null, address); + } +}