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]