This is an automated email from the ASF dual-hosted git repository.

cnauroth pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/hadoop.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 6732b6e7c4f HADOOP-19821. [JDK25] Token initialization fails with 
NoClassDefFoundError
6732b6e7c4f is described below

commit 6732b6e7c4f6311cbecb6f0428e43c3231d64999
Author: Cheng Pan <[email protected]>
AuthorDate: Mon Feb 23 17:39:22 2026 +0000

    HADOOP-19821. [JDK25] Token initialization fails with NoClassDefFoundError
    
    Closes #8265
    
    Signed-off-by: Chris Nauroth <[email protected]>
---
 .../main/java/org/apache/hadoop/fs/FileSystem.java |  8 +++++--
 .../hadoop/security/token/DtFileOperations.java    |  8 +++++--
 .../org/apache/hadoop/security/token/Token.java    | 28 ++++++++++++----------
 .../java/org/apache/hadoop/mapreduce/Cluster.java  |  5 ++--
 .../org/apache/hadoop/mapreduce/TestCluster.java   | 20 ++++++++++++----
 5 files changed, 44 insertions(+), 25 deletions(-)

diff --git 
a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileSystem.java
 
b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileSystem.java
index 957cac07d97..ecdcfd6300d 100644
--- 
a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileSystem.java
+++ 
b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileSystem.java
@@ -3520,9 +3520,13 @@ private static void loadFileSystems() {
       if (!FILE_SYSTEMS_LOADED) {
         ServiceLoader<FileSystem> serviceLoader = 
ServiceLoader.load(FileSystem.class);
         Iterator<FileSystem> it = serviceLoader.iterator();
-        while (it.hasNext()) {
+        // both "hasNext()" and "next()" calls might trigger implementations 
loading.
+        while (true) {
           FileSystem fs;
           try {
+            if (!it.hasNext()) {
+              break;
+            }
             fs = it.next();
             try {
               SERVICE_FILE_SYSTEMS.put(fs.getScheme(), fs.getClass());
@@ -3536,7 +3540,7 @@ private static void loadFileSystems() {
                   ClassUtil.findContainingJar(fs.getClass()));
               LOGGER.info("Full exception loading: {}", fs, e);
             }
-          } catch (ServiceConfigurationError ee) {
+          } catch (ServiceConfigurationError | LinkageError ee) {
             LOGGER.warn("Cannot load filesystem", ee);
           }
         }
diff --git 
a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/DtFileOperations.java
 
b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/DtFileOperations.java
index 5d80a45f79f..7cd9e91917e 100644
--- 
a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/DtFileOperations.java
+++ 
b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/DtFileOperations.java
@@ -180,11 +180,15 @@ public static void getTokenFile(File tokenFile, String 
fileFormat,
         Credentials.readTokenStorageFile(tokenFile, conf) : new Credentials();
     ServiceLoader<DtFetcher> loader = ServiceLoader.load(DtFetcher.class);
     Iterator<DtFetcher> iterator = loader.iterator();
-    while (iterator.hasNext()) {
+    // both "hasNext()" and "next()" calls might trigger implementations 
loading.
+    while (true) {
       DtFetcher fetcher;
       try {
+        if (!iterator.hasNext()) {
+          break;
+        }
         fetcher = iterator.next();
-      } catch (ServiceConfigurationError e) {
+      } catch (ServiceConfigurationError | LinkageError e) {
         // failure to load a token implementation
         // log at debug and continue.
         LOG.debug("Failed to load token fetcher implementation", e);
diff --git 
a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/Token.java
 
b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/Token.java
index 3ea32bc41ed..8186420bbe1 100644
--- 
a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/Token.java
+++ 
b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/Token.java
@@ -18,7 +18,6 @@
 
 package org.apache.hadoop.security.token;
 
-import org.apache.hadoop.thirdparty.com.google.common.collect.Maps;
 import org.apache.hadoop.thirdparty.com.google.common.primitives.Bytes;
 
 import org.apache.commons.codec.binary.Base64;
@@ -33,11 +32,7 @@
 
 import java.io.*;
 import java.security.MessageDigest;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.ServiceConfigurationError;
-import java.util.ServiceLoader;
-import java.util.UUID;
+import java.util.*;
 
 /**
  * The client-side form of the token.
@@ -128,13 +123,16 @@ public byte[] getIdentifier() {
     Class<? extends TokenIdentifier> cls = null;
     synchronized (Token.class) {
       if (tokenKindMap == null) {
-        tokenKindMap = Maps.newHashMap();
-        // start the service load process; it's only in the "next()" calls
-        // where implementations are loaded.
+        tokenKindMap = new HashMap<>();
+        // start the service load process;
+        // both "hasNext()" and "next()" calls might trigger implementations 
loading.
         final Iterator<TokenIdentifier> tokenIdentifiers =
             ServiceLoader.load(TokenIdentifier.class).iterator();
-        while (tokenIdentifiers.hasNext()) {
+        while (true) {
           try {
+            if (!tokenIdentifiers.hasNext()) {
+              break;
+            }
             TokenIdentifier id = tokenIdentifiers.next();
             LOG.debug("Added {}:{} into tokenKindMap", id.getKind(), 
id.getClass());
             tokenKindMap.put(id.getKind(), id.getClass());
@@ -451,7 +449,7 @@ public String buildCacheKey() {
         Bytes.concat(kind.getBytes(), identifier, password)).toString();
   }
 
-  private static ServiceLoader<TokenRenewer> renewers =
+  private final static ServiceLoader<TokenRenewer> renewers =
       ServiceLoader.load(TokenRenewer.class);
 
   private synchronized TokenRenewer getRenewer() throws IOException {
@@ -461,14 +459,18 @@ private synchronized TokenRenewer getRenewer() throws 
IOException {
     renewer = TRIVIAL_RENEWER;
     synchronized (renewers) {
       Iterator<TokenRenewer> it = renewers.iterator();
-      while (it.hasNext()) {
+      // both "hasNext()" and "next()" calls might trigger implementations 
loading.
+      while (true) {
         try {
+          if (!it.hasNext()) {
+            break;
+          }
           TokenRenewer candidate = it.next();
           if (candidate.handleKind(this.kind)) {
             renewer = candidate;
             return renewer;
           }
-        } catch (ServiceConfigurationError e) {
+        } catch (ServiceConfigurationError | LinkageError e) {
           // failure to load a token implementation
           // log at debug and continue.
           LOG.debug("Failed to load token renewer implementation", e);
diff --git 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/Cluster.java
 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/Cluster.java
index 050d0e5a6e0..6688f5eb944 100644
--- 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/Cluster.java
+++ 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/Cluster.java
@@ -76,13 +76,12 @@ private void initProviderList() {
     if (providerList == null) {
       synchronized (frameworkLoader) {
         if (providerList == null) {
-          List<ClientProtocolProvider> localProviderList =
-              new ArrayList<ClientProtocolProvider>();
+          List<ClientProtocolProvider> localProviderList = new ArrayList<>();
           try {
             for (ClientProtocolProvider provider : frameworkLoader) {
               localProviderList.add(provider);
             }
-          } catch(ServiceConfigurationError e) {
+          } catch(ServiceConfigurationError | LinkageError e) {
             LOG.info("Failed to instantiate ClientProtocolProvider, please "
                          + "check the /META-INF/services/org.apache."
                          + "hadoop.mapreduce.protocol.ClientProtocolProvider "
diff --git 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/test/java/org/apache/hadoop/mapreduce/TestCluster.java
 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/test/java/org/apache/hadoop/mapreduce/TestCluster.java
index 16732505a7f..4aad908736a 100644
--- 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/test/java/org/apache/hadoop/mapreduce/TestCluster.java
+++ 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/test/java/org/apache/hadoop/mapreduce/TestCluster.java
@@ -38,16 +38,16 @@
  * Testing the Cluster initialization.
  */
 public class TestCluster {
-  @Test
+
   @SuppressWarnings("unchecked")
-  public void testProtocolProviderCreation() throws Exception {
-    Iterator iterator = mock(Iterator.class);
+  public void testProtocolProviderCreation(Throwable error) throws Exception {
+    Iterator<ClientProtocolProvider> iterator = mock(Iterator.class);
     when(iterator.hasNext()).thenReturn(true, true, true, true);
     when(iterator.next()).thenReturn(getClientProtocolProvider())
-        .thenThrow(new ServiceConfigurationError("Test error"))
+        .thenThrow(error)
         .thenReturn(getClientProtocolProvider());
 
-    Iterable frameworkLoader = mock(Iterable.class);
+    Iterable<ClientProtocolProvider> frameworkLoader = mock(Iterable.class);
     when(frameworkLoader.iterator()).thenReturn(iterator);
 
     Cluster.frameworkLoader = frameworkLoader;
@@ -60,6 +60,16 @@ public void testProtocolProviderCreation() throws Exception {
     verify(iterator, times(2)).next();
   }
 
+  @Test
+  public void testThrowServiceConfigurationError() throws Exception {
+    testProtocolProviderCreation(new ServiceConfigurationError("Test error"));
+  }
+
+  @Test
+  public void testThrowNoClassDefFoundError() throws Exception {
+    testProtocolProviderCreation(new NoClassDefFoundError("Test error"));
+  }
+
   public ClientProtocolProvider getClientProtocolProvider() {
     return new ClientProtocolProvider() {
       @Override


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to