Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 153 additions & 2 deletions src/java.base/share/classes/java/net/InetAddress.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import jdk.internal.util.Exceptions;
import jdk.internal.access.JavaNetInetAddressAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.event.DnsLookupEvent;
import jdk.internal.misc.Blocker;
import jdk.internal.misc.VM;
import jdk.internal.vm.annotation.Stable;
Expand Down Expand Up @@ -982,18 +983,36 @@
public InetAddress[] get() {
long now = System.nanoTime();
if ((refreshTime - now) < 0L && lookupLock.tryLock()) {
// JFR event tracking for background DNS refresh (actual network query)
long jfrStart = DnsLookupEvent.enabled() ? DnsLookupEvent.timestamp() : 0L;
try {
// cachePolicy is in [s] - we need [ns]
refreshTime = now + InetAddressCachePolicy.get() * 1000_000_000L;
// getAddressesFromNameService returns non-empty/non-null value
inetAddresses = getAddressesFromNameService(host);
InetAddress[] refreshedAddresses = getAddressesFromNameService(host);

Check failure on line 993 in src/java.base/share/classes/java/net/InetAddress.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28110

Whitespace error

Column 0: trailing whitespace Column 1: trailing whitespace Column 2: trailing whitespace Column 3: trailing whitespace Column 4: trailing whitespace Column 5: trailing whitespace Column 6: trailing whitespace Column 7: trailing whitespace Column 8: trailing whitespace Column 9: trailing whitespace Column 10: trailing whitespace Column 11: trailing whitespace Column 12: trailing whitespace Column 13: trailing whitespace Column 14: trailing whitespace Column 15: trailing whitespace Column 16: trailing whitespace Column 17: trailing whitespace Column 18: trailing whitespace Column 19: trailing whitespace
// Emit JFR event for successful background DNS refresh (actual network query)
if (DnsLookupEvent.enabled()) {
DnsLookupEvent.offerNetworkQuery(jfrStart, host, refreshedAddresses, true);
}

Check failure on line 998 in src/java.base/share/classes/java/net/InetAddress.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28110

Whitespace error

Column 0: trailing whitespace Column 1: trailing whitespace Column 2: trailing whitespace Column 3: trailing whitespace Column 4: trailing whitespace Column 5: trailing whitespace Column 6: trailing whitespace Column 7: trailing whitespace Column 8: trailing whitespace Column 9: trailing whitespace Column 10: trailing whitespace Column 11: trailing whitespace Column 12: trailing whitespace Column 13: trailing whitespace Column 14: trailing whitespace Column 15: trailing whitespace Column 16: trailing whitespace Column 17: trailing whitespace Column 18: trailing whitespace Column 19: trailing whitespace
inetAddresses = refreshedAddresses;
// don't update the "expirySet", will do that later
staleTime = refreshTime + InetAddressCachePolicy.getStale() * 1000_000_000L;
} catch (UnknownHostException ignore) {
} catch (UnknownHostException uhe) {
// Emit JFR event for failed background DNS refresh (actual network query)
if (DnsLookupEvent.enabled() && jfrStart != 0L) {
DnsLookupEvent.offerNetworkQuery(jfrStart, host, uhe.getMessage());
}
// Ignore exception, continue using stale data
} finally {
lookupLock.unlock();
}
}

Check failure on line 1012 in src/java.base/share/classes/java/net/InetAddress.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28110

Whitespace error

Column 0: trailing whitespace Column 1: trailing whitespace Column 2: trailing whitespace Column 3: trailing whitespace Column 4: trailing whitespace Column 5: trailing whitespace Column 6: trailing whitespace Column 7: trailing whitespace Column 8: trailing whitespace Column 9: trailing whitespace Column 10: trailing whitespace Column 11: trailing whitespace
// Note: Cache hit events (including stale data) are recorded in getAllByName0()
// to avoid duplicate recording. This method only records actual network queries
// during background refresh.
return inetAddresses;
}

Expand Down Expand Up @@ -1052,6 +1071,9 @@
}
// still us ?
if (addresses == this) {
// JFR event tracking for actual DNS network query
long jfrStart = DnsLookupEvent.enabled() ? DnsLookupEvent.timestamp() : 0L;

Check failure on line 1076 in src/java.base/share/classes/java/net/InetAddress.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28110

Whitespace error

Column 0: trailing whitespace Column 1: trailing whitespace Column 2: trailing whitespace Column 3: trailing whitespace Column 4: trailing whitespace Column 5: trailing whitespace Column 6: trailing whitespace Column 7: trailing whitespace Column 8: trailing whitespace Column 9: trailing whitespace Column 10: trailing whitespace Column 11: trailing whitespace Column 12: trailing whitespace Column 13: trailing whitespace Column 14: trailing whitespace Column 15: trailing whitespace Column 16: trailing whitespace Column 17: trailing whitespace Column 18: trailing whitespace Column 19: trailing whitespace
// lookup name services
InetAddress[] inetAddresses;
UnknownHostException ex;
Expand All @@ -1060,10 +1082,20 @@
inetAddresses = getAddressesFromNameService(host);
ex = null;
cachePolicy = InetAddressCachePolicy.get();

Check failure on line 1085 in src/java.base/share/classes/java/net/InetAddress.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28110

Whitespace error

Column 0: trailing whitespace Column 1: trailing whitespace Column 2: trailing whitespace Column 3: trailing whitespace Column 4: trailing whitespace Column 5: trailing whitespace Column 6: trailing whitespace Column 7: trailing whitespace Column 8: trailing whitespace Column 9: trailing whitespace Column 10: trailing whitespace Column 11: trailing whitespace Column 12: trailing whitespace Column 13: trailing whitespace Column 14: trailing whitespace Column 15: trailing whitespace Column 16: trailing whitespace Column 17: trailing whitespace Column 18: trailing whitespace Column 19: trailing whitespace Column 20: trailing whitespace Column 21: trailing whitespace Column 22: trailing whitespace Column 23: trailing whitespace
// Emit JFR event for successful actual DNS network query
if (DnsLookupEvent.enabled()) {
DnsLookupEvent.offerNetworkQuery(jfrStart, host, inetAddresses, true);
}
} catch (UnknownHostException uhe) {
inetAddresses = null;
ex = uhe;
cachePolicy = InetAddressCachePolicy.getNegative();

Check failure on line 1094 in src/java.base/share/classes/java/net/InetAddress.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28110

Whitespace error

Column 0: trailing whitespace Column 1: trailing whitespace Column 2: trailing whitespace Column 3: trailing whitespace Column 4: trailing whitespace Column 5: trailing whitespace Column 6: trailing whitespace Column 7: trailing whitespace Column 8: trailing whitespace Column 9: trailing whitespace Column 10: trailing whitespace Column 11: trailing whitespace Column 12: trailing whitespace Column 13: trailing whitespace Column 14: trailing whitespace Column 15: trailing whitespace Column 16: trailing whitespace Column 17: trailing whitespace Column 18: trailing whitespace Column 19: trailing whitespace Column 20: trailing whitespace Column 21: trailing whitespace Column 22: trailing whitespace Column 23: trailing whitespace
// Emit JFR event for failed actual DNS network query
if (DnsLookupEvent.enabled()) {
DnsLookupEvent.offerNetworkQuery(jfrStart, host, uhe.getMessage());
}
}
// remove or replace us with cached addresses according to cachePolicy
if (cachePolicy == InetAddressCachePolicy.NEVER) {
Expand Down Expand Up @@ -1671,6 +1703,9 @@
}
}

// JFR event tracking for cache lookup
long jfrStart = DnsLookupEvent.enabled() ? DnsLookupEvent.timestamp() : 0L;

// look-up or remove from cache
Addresses addrs;
if (useCache) {
Expand All @@ -1686,6 +1721,48 @@
}
}

// Check if we have a cached result
if (addrs != null && (addrs instanceof CachedLookup || addrs instanceof ValidCachedLookup)) {
// Cached result - record event with cache information
CachedLookup cached = (CachedLookup) addrs;
boolean isStale = false;
long ttlSeconds = 0;

Check failure on line 1730 in src/java.base/share/classes/java/net/InetAddress.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28110

Whitespace error

Column 0: trailing whitespace Column 1: trailing whitespace Column 2: trailing whitespace Column 3: trailing whitespace Column 4: trailing whitespace Column 5: trailing whitespace Column 6: trailing whitespace Column 7: trailing whitespace Column 8: trailing whitespace Column 9: trailing whitespace Column 10: trailing whitespace Column 11: trailing whitespace
if (cached instanceof ValidCachedLookup) {
ValidCachedLookup validCached = (ValidCachedLookup) cached;
long refreshTime = validCached.refreshTime;
isStale = (refreshTime - now) < 0L;
if (validCached.expiryTime > 0) {
long remainingNanos = validCached.expiryTime - now;
ttlSeconds = remainingNanos > 0 ? remainingNanos / 1_000_000_000L : 0;
} else {
ttlSeconds = -1; // Forever
}
} else {
if (cached.expiryTime > 0) {
long remainingNanos = cached.expiryTime - now;
ttlSeconds = remainingNanos > 0 ? remainingNanos / 1_000_000_000L : 0;
} else {
ttlSeconds = -1; // Forever
}
}

try {
InetAddress[] result = addrs.get().clone();
// Record cached success result
if (DnsLookupEvent.enabled()) {
DnsLookupEvent.offerCachedResult(jfrStart, host, result, true, ttlSeconds, isStale);
}
return result;
} catch (UnknownHostException e) {
// Record cached error result
if (DnsLookupEvent.enabled()) {
DnsLookupEvent.offerCachedError(jfrStart, host, e.getMessage(), ttlSeconds);
}
throw e;
}
}

if (addrs == null) {
// create a NameServiceAddresses instance which will look up
// the name service and install it within cache...
Expand All @@ -1695,10 +1772,50 @@
);
if (oldAddrs != null) { // lost putIfAbsent race
addrs = oldAddrs;
// If we got a cached entry from the race, handle it
if (oldAddrs instanceof CachedLookup || oldAddrs instanceof ValidCachedLookup) {
CachedLookup cached = (CachedLookup) oldAddrs;
// Reuse 'now' variable defined earlier in the method
boolean isStale = false;
long ttlSeconds = 0;

Check failure on line 1781 in src/java.base/share/classes/java/net/InetAddress.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28110

Whitespace error

Column 0: trailing whitespace Column 1: trailing whitespace Column 2: trailing whitespace Column 3: trailing whitespace Column 4: trailing whitespace Column 5: trailing whitespace Column 6: trailing whitespace Column 7: trailing whitespace Column 8: trailing whitespace Column 9: trailing whitespace Column 10: trailing whitespace Column 11: trailing whitespace Column 12: trailing whitespace Column 13: trailing whitespace Column 14: trailing whitespace Column 15: trailing whitespace Column 16: trailing whitespace Column 17: trailing whitespace Column 18: trailing whitespace Column 19: trailing whitespace
if (cached instanceof ValidCachedLookup) {
ValidCachedLookup validCached = (ValidCachedLookup) cached;
long refreshTime = validCached.refreshTime;
isStale = (refreshTime - now) < 0L;
if (validCached.expiryTime > 0) {
long remainingNanos = validCached.expiryTime - now;
ttlSeconds = remainingNanos > 0 ? remainingNanos / 1_000_000_000L : 0;
} else {
ttlSeconds = -1;
}
} else {
if (cached.expiryTime > 0) {
long remainingNanos = cached.expiryTime - now;
ttlSeconds = remainingNanos > 0 ? remainingNanos / 1_000_000_000L : 0;
} else {
ttlSeconds = -1;
}
}

try {
InetAddress[] result = addrs.get().clone();
if (DnsLookupEvent.enabled()) {
DnsLookupEvent.offerCachedResult(jfrStart, host, result, true, ttlSeconds, isStale);
}
return result;
} catch (UnknownHostException e) {
if (DnsLookupEvent.enabled()) {
DnsLookupEvent.offerCachedError(jfrStart, host, e.getMessage(), ttlSeconds);
}
throw e;
}
}
}
}

// ask Addresses to get an array of InetAddress(es) and clone it
// Note: JFR events for actual DNS network queries are recorded in NameServiceAddresses.get()
return addrs.get().clone();
}

Expand Down Expand Up @@ -1882,4 +1999,38 @@
throw new UnknownHostException("NUL character not allowed in hostname");
}
}

/**
* Collect DNS cache statistics for JFR periodic events.
* This method is called periodically by JFR to emit cache statistics.
*
* @return array of three long values: [cacheSize, staleEntries, entriesRemoved]
*/
public static long[] getDnsCacheStatistics() {
long now = System.nanoTime();
long cacheSize = cache.size();
long staleEntries = 0;
long entriesRemoved = 0;

// Count stale entries
for (CachedLookup caddrs : expirySet) {
if (caddrs instanceof ValidCachedLookup) {
ValidCachedLookup validCached = (ValidCachedLookup) caddrs;
if ((validCached.refreshTime - now) < 0L && (validCached.staleTime - now) >= 0L) {
staleEntries++;
}
}
}

// Count entries that would be removed (expired but not yet cleaned)
for (CachedLookup caddrs : expirySet) {
if ((caddrs.expiryTime - now) < 0L) {
entriesRemoved++;
} else {
break; // entries are ordered by expiry time
}
}

return new long[]{cacheSize, staleEntries, entriesRemoved};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2025, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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
* accompanies 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 jdk.internal.event;

/**
* A JFR event for DNS cache statistics. This event is mirrored in
* {@code jdk.jfr.events.DnsCacheStatisticsEvent } where the metadata for the event is
* provided with annotations. Some of the methods are replaced by generated
* methods when jfr is enabled. Note that the order of the arguments of the
* {@link #commit(long, long, long, long)} method
* must be the same as the order of the fields.
*/
public class DnsCacheStatisticsEvent extends Event {

// THE ORDER OF THE FOLLOWING FIELDS IS IMPORTANT!
// The order must match the argument order of the generated commit method.
public long cacheSize;
public long staleEntries;
public long entriesRemoved;

/**
* Actually commit a DNS cache statistics event. The implementation
* of this method is generated automatically if jfr is enabled.
* The order of the fields must be the same as the parameters in this method.
* {@code commit(..., long, long, long)}
*
* @param timestamp timestamp when the statistics were collected
* @param cacheSize current number of entries in the DNS cache
* @param staleEntries number of stale entries in the cache
* @param entriesRemoved number of entries removed during cleanup
*/
public static void commit(long timestamp, long cacheSize, long staleEntries, long entriesRemoved) {
// Generated by JFR
}

/**
* Determine if this kind of event is enabled. The implementation
* of this method is generated automatically if jfr is enabled.
*
* @return true if DNS cache statistics events are enabled, false otherwise
*/
public static boolean enabled() {
// Generated by JFR
return false;
}

/**
* Fetch the current timestamp in nanoseconds. This method is used
* to determine when statistics were collected. The implementation
* of this method is generated automatically if jfr is enabled.
*
* @return the current timestamp value
*/
public static long timestamp() {
// Generated by JFR
return 0L;
}
}

Loading