8225239: Refactor NetworkInterface lookups

Reviewed-by: michaelm, dfuchs, chegar
This commit is contained in:
Claes Redestad 2019-07-05 13:40:29 +02:00
parent eb2818421a
commit 7f1f9a50ae
8 changed files with 417 additions and 144 deletions

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,8 @@
package java.net; package java.net;
import java.io.IOException; import java.io.IOException;
import static java.net.InetAddress.IPv6;
import static java.net.InetAddress.PREFER_IPV6_VALUE; import static java.net.InetAddress.PREFER_IPV6_VALUE;
import static java.net.InetAddress.PREFER_SYSTEM_VALUE; import static java.net.InetAddress.PREFER_SYSTEM_VALUE;
@ -70,7 +72,7 @@ class Inet6AddressImpl implements InetAddressImpl {
* stack system). * stack system).
*/ */
java.util.Enumeration<InetAddress> it = netif.getInetAddresses(); java.util.Enumeration<InetAddress> it = netif.getInetAddresses();
InetAddress inetaddr = null; InetAddress inetaddr;
while (it.hasMoreElements()) { while (it.hasMoreElements()) {
inetaddr = it.nextElement(); inetaddr = it.nextElement();
if (inetaddr.getClass().isInstance(addr)) { if (inetaddr.getClass().isInstance(addr)) {
@ -110,20 +112,23 @@ class Inet6AddressImpl implements InetAddressImpl {
boolean preferIPv6Address = boolean preferIPv6Address =
InetAddress.preferIPv6Address == PREFER_IPV6_VALUE || InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE; InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE;
InetAddress loopback4 = (new Inet4AddressImpl()).loopbackAddress();
InetAddress loopback6 = new Inet6Address("localhost", 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, new byte[]{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}); 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01});
// Order the candidate addresses by preference. } else {
InetAddress[] addresses = preferIPv6Address address = new Inet4Address("localhost", new byte[]{ 0x7f,0x00,0x00,0x01 });
? new InetAddress[] {loopback6, loopback4} }
: new InetAddress[] {loopback4, loopback6}; if (i == 0) {
// In case of failure, default to the preferred address. // In case of failure, default to the preferred address.
loopbackAddress = addresses[0]; loopbackAddress = address;
// Pick the first candidate address that actually exists. }
for (InetAddress address : addresses) {
try { try {
if (NetworkInterface.getByInetAddress(address) == null) { if (!NetworkInterface.isBoundInetAddress(address)) {
continue; continue;
} }
} catch (SocketException e) { } catch (SocketException e) {

View File

@ -290,7 +290,7 @@ class InetAddress implements java.io.Serializable {
} }
/* Used to store the name service provider */ /* 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. * Used to store the best available hostname.
@ -305,8 +305,7 @@ class InetAddress implements java.io.Serializable {
* Load net library into runtime, and perform initializations. * Load net library into runtime, and perform initializations.
*/ */
static { static {
String str = java.security.AccessController.doPrivileged( String str = GetPropertyAction.privilegedGetProperty("java.net.preferIPv6Addresses");
new GetPropertyAction("java.net.preferIPv6Addresses"));
if (str == null) { if (str == null) {
preferIPv6Address = PREFER_IPV4_VALUE; preferIPv6Address = PREFER_IPV4_VALUE;
} else if (str.equalsIgnoreCase("true")) { } else if (str.equalsIgnoreCase("true")) {

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -321,17 +321,16 @@ public final class NetworkInterface {
if (addr == null) { if (addr == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
if (addr instanceof Inet4Address) {
Inet4Address inet4Address = (Inet4Address) addr; if (addr.holder.family == InetAddress.IPv4) {
if (inet4Address.holder.family != InetAddress.IPv4) { if (!(addr instanceof Inet4Address)) {
throw new IllegalArgumentException("invalid family type: " throw new IllegalArgumentException("invalid family type: "
+ inet4Address.holder.family); + addr.holder.family);
} }
} else if (addr instanceof Inet6Address) { } else if (addr.holder.family == InetAddress.IPv6) {
Inet6Address inet6Address = (Inet6Address) addr; if (!(addr instanceof Inet6Address)) {
if (inet6Address.holder.family != InetAddress.IPv6) {
throw new IllegalArgumentException("invalid family type: " throw new IllegalArgumentException("invalid family type: "
+ inet6Address.holder.family); + addr.holder.family);
} }
} else { } else {
throw new IllegalArgumentException("invalid address type: " + addr); throw new IllegalArgumentException("invalid address type: " + addr);
@ -394,6 +393,23 @@ public final class NetworkInterface {
} }
} }
/**
* 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 <T> Enumeration<T> enumerationFromArray(T[] a) { private static <T> Enumeration<T> enumerationFromArray(T[] a) {
return new Enumeration<>() { return new Enumeration<>() {
int i = 0; int i = 0;
@ -431,6 +447,9 @@ public final class NetworkInterface {
private static native NetworkInterface getByIndex0(int index) private static native NetworkInterface getByIndex0(int index)
throws SocketException; throws SocketException;
private static native boolean boundInetAddress0(InetAddress addr)
throws SocketException;
private static native NetworkInterface getByInetAddress0(InetAddress addr) private static native NetworkInterface getByInetAddress0(InetAddress addr)
throws SocketException; throws SocketException;

View File

@ -320,33 +320,9 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
return obj; return obj;
} }
/* // Return the interface in ifs that iaObj is bound to, if any - otherwise NULL
* Class: java_net_NetworkInterface static netif* find_bound_interface(JNIEnv *env, netif* ifs, jobject iaObj, int family) {
* Method: getByInetAddress0 netif* curr = ifs;
* 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;
while (curr != NULL) { while (curr != NULL) {
netaddr *addrP = curr->addr; netaddr *addrP = curr->addr;
@ -359,11 +335,10 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
((struct sockaddr_in *)addrP->addr)->sin_addr.s_addr); ((struct sockaddr_in *)addrP->addr)->sin_addr.s_addr);
int address2 = getInetAddress_addr(env, iaObj); int address2 = getInetAddress_addr(env, iaObj);
if ((*env)->ExceptionCheck(env)) { if ((*env)->ExceptionCheck(env)) {
goto cleanup; return NULL;
} }
if (address1 == address2) { if (address1 == address2) {
match = JNI_TRUE; return curr;
break;
} }
} else if (family == AF_INET6) { } else if (family == AF_INET6) {
jbyte *bytes = (jbyte *)&( jbyte *bytes = (jbyte *)&(
@ -383,30 +358,117 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
i++; i++;
} }
if (i >= 16) { if (i >= 16) {
match = JNI_TRUE; return curr;
break;
} }
} }
} }
if (match) {
break;
}
addrP = addrP->next; addrP = addrP->next;
} }
if (match) {
break;
}
curr = curr->next; curr = curr->next;
} }
// if found create a NetworkInterface return NULL;
if (match) { }
obj = createNetworkInterface(env, curr);
/*
* 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: 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 (curr != NULL) {
obj = createNetworkInterface(env, curr);
}
// release the interface list // release the interface list
freeif(ifs); freeif(ifs);

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
#include "net_util.h" #include "net_util.h"
#include "NetworkInterface.h" #include "NetworkInterface.h"
#include "java_net_InetAddress.h"
#include "java_net_NetworkInterface.h" #include "java_net_NetworkInterface.h"
/* /*
@ -347,7 +348,7 @@ int enumInterfaces(JNIEnv *env, netif **netifPP)
/* /*
* Free the interface table and return the interface list * Free the interface table and return the interface list
*/ */
if (tableP) { if (tableP != NULL) {
free(tableP); free(tableP);
} }
*netifPP = netifP; *netifPP = netifP;
@ -355,24 +356,13 @@ int enumInterfaces(JNIEnv *env, netif **netifPP)
} }
/* /*
* Enumerate the IP addresses on an interface using the IP helper library * Enumerate all addresses 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.
*/ */
int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP) int lookupIPAddrTable(JNIEnv *env, MIB_IPADDRTABLE **tablePP)
{ {
MIB_IPADDRTABLE *tableP; MIB_IPADDRTABLE *tableP;
ULONG size; ULONG size;
DWORD ret; DWORD ret;
DWORD i;
netaddr *netaddrP;
int count = 0;
unsigned long mask;
/* /*
* Use GetIpAddrTable to enumerate the IP Addresses * Use GetIpAddrTable to enumerate the IP Addresses
*/ */
@ -396,7 +386,7 @@ int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP)
ret = GetIpAddrTable(tableP, &size, FALSE); ret = GetIpAddrTable(tableP, &size, FALSE);
} }
if (ret != NO_ERROR) { if (ret != NO_ERROR) {
if (tableP) { if (tableP != NULL) {
free(tableP); free(tableP);
} }
JNU_ThrowByName(env, "java/lang/Error", JNU_ThrowByName(env, "java/lang/Error",
@ -405,11 +395,30 @@ int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP)
// GetIpAddrTable in pure IPv6 environment // GetIpAddrTable in pure IPv6 environment
return -2; 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 * Iterate through the table to find the addresses with the
* matching dwIndex. Ignore 0.0.0.0 addresses. * matching dwIndex. Ignore 0.0.0.0 addresses.
*/ */
if (tableP == NULL)
return 0;
count = 0; count = 0;
netaddrP = NULL; netaddrP = NULL;
@ -474,10 +483,30 @@ int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP)
} }
*netaddrPP = netaddrP; *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); free(tableP);
return count; return count;
} }
/* /*
* Class: java_net_NetworkInterface * Class: java_net_NetworkInterface
* Method: init * Method: init
@ -758,6 +787,50 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
return netifObj; 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 * Class: java_net_NetworkInterface
* Method: getByInetAddress0 * Method: getByInetAddress0
@ -767,11 +840,11 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
(JNIEnv *env, jclass cls, jobject iaObj) (JNIEnv *env, jclass cls, jobject iaObj)
{ {
netif *ifList, *curr; netif *ifList, *curr;
MIB_IPADDRTABLE *tableP;
jobject netifObj = NULL; jobject netifObj = NULL;
jint addr = getInetAddress_addr(env, iaObj); jint addr = getInetAddress_addr(env, iaObj);
JNU_CHECK_EXCEPTION_RETURN(env, NULL); JNU_CHECK_EXCEPTION_RETURN(env, NULL);
// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
if (ipv6_available()) { if (ipv6_available()) {
return Java_java_net_NetworkInterface_getByInetAddress0_XP (env, cls, iaObj); return Java_java_net_NetworkInterface_getByInetAddress0_XP (env, cls, iaObj);
} }
@ -785,6 +858,8 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
* Enumerate the addresses on each interface until we find a * Enumerate the addresses on each interface until we find a
* matching address. * matching address.
*/ */
tableP = NULL;
if (lookupIPAddrTable(env, &tableP) >= 0) {
curr = ifList; curr = ifList;
while (curr != NULL) { while (curr != NULL) {
int count; int count;
@ -792,9 +867,10 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
netaddr *addrP; netaddr *addrP;
/* enumerate the addresses on this interface */ /* enumerate the addresses on this interface */
count = enumAddresses_win(env, curr, &addrList); count = enumAddresses_win_ipaddrtable(env, curr, &addrList, tableP);
if (count < 0) { if (count < 0) {
free_netif(ifList); free_netif(ifList);
free(tableP);
return NULL; return NULL;
} }
@ -821,6 +897,11 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
/* on next interface */ /* on next interface */
curr = curr->next; curr = curr->next;
} }
}
/* release the IP address table */
if (tableP != NULL)
free(tableP);
/* release the interface list */ /* release the interface list */
free_netif(ifList); free_netif(ifList);

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -33,7 +33,9 @@
* and getByAddress. * 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 enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP);
extern int lookupIPAddrTable(JNIEnv *env, MIB_IPADDRTABLE **tablePP);
int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP); int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP);
#ifdef DEBUG #ifdef DEBUG
@ -239,6 +241,7 @@ static int ipinflen = 2048;
int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP) int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP)
{ {
DWORD ret; DWORD ret;
MIB_IPADDRTABLE *tableP;
IP_ADAPTER_ADDRESSES *ptr, *adapters=NULL; IP_ADAPTER_ADDRESSES *ptr, *adapters=NULL;
ULONG len=ipinflen, count=0; ULONG len=ipinflen, count=0;
netif *nif=NULL, *dup_nif, *last=NULL, *loopif=NULL, *curr; netif *nif=NULL, *dup_nif, *last=NULL, *loopif=NULL, *curr;
@ -271,10 +274,15 @@ int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP)
// Retrieve IPv4 addresses with the IP Helper API // Retrieve IPv4 addresses with the IP Helper API
curr = *netifPP; curr = *netifPP;
ret = lookupIPAddrTable(env, &tableP);
if (ret < 0) {
return -1;
}
while (curr != NULL) { while (curr != NULL) {
netaddr *netaddrP; netaddr *netaddrP;
ret = enumAddresses_win(env, curr, &netaddrP); ret = enumAddresses_win_ipaddrtable(env, curr, &netaddrP, tableP);
if (ret == -1) { if (ret == -1) {
free(tableP);
return -1; return -1;
} else if (ret == -2) { } else if (ret == -2) {
if ((*env)->ExceptionCheck(env)) { if ((*env)->ExceptionCheck(env)) {
@ -287,7 +295,7 @@ int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP)
curr = curr->next; curr = curr->next;
} }
} }
free(tableP);
ret = getAdapters (env, &adapters); ret = getAdapters (env, &adapters);
if (ret != ERROR_SUCCESS) { if (ret != ERROR_SUCCESS) {
goto err; goto err;

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,17 +23,21 @@
/** /**
* @test * @test
* @bug 8179559 * @bug 8179559 8225239
*/ */
import java.net.InetAddress; import java.net.InetAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.util.Enumeration; import java.util.Enumeration;
import java.lang.reflect.Method;
public class NetworkInterfaceRetrievalTests { public class NetworkInterfaceRetrievalTests {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
int checkFailureCount = 0; int checkFailureCount = 0;
Method isBound = NetworkInterface.class.getDeclaredMethod("isBoundInetAddress", InetAddress.class);
isBound.setAccessible(true);
try { try {
Enumeration<NetworkInterface> en = NetworkInterface Enumeration<NetworkInterface> en = NetworkInterface
.getNetworkInterfaces(); .getNetworkInterfaces();
@ -58,6 +62,13 @@ public class NetworkInterfaceRetrievalTests {
checkFailureCount++; 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++;
}
} }
} }

View File

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