diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Preconditions.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Preconditions.java
new file mode 100644
index 0000000000..67d6e6cc9f
--- /dev/null
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Preconditions.java
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.util;
+
+import java.util.function.Supplier;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+/**
+ *
This class replaces {@code guava.Preconditions} which provides helpers
+ * to validate the following conditions:
+ *
+ * - An invalid {@code null} obj causes a {@link NullPointerException}.
+ * - An invalid argument causes an {@link IllegalArgumentException}.
+ * - An invalid state causes an {@link IllegalStateException}.
+ * - An invalid index causes an {@link IndexOutOfBoundsException}.
+ *
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public final class Preconditions {
+ private static final Logger LOG =
+ LoggerFactory.getLogger(Preconditions.class);
+
+ private static final String VALIDATE_IS_NOT_NULL_EX_MESSAGE =
+ "The argument object is NULL";
+
+ private Preconditions() {
+ }
+
+ /**
+ * Preconditions that the specified argument is not {@code null},
+ * throwing a NPE exception otherwise.
+ *
+ *
The message of the exception is
+ * "The validated object is null".
+ *
+ * @param the object type
+ * @param obj the object to check
+ * @return the validated object
+ * @throws NullPointerException if the object is {@code null}
+ * @see #checkNotNull(Object, Object)
+ */
+ public static T checkNotNull(final T obj) {
+ return checkNotNull(obj, VALIDATE_IS_NOT_NULL_EX_MESSAGE);
+ }
+
+ /**
+ * Preconditions that the specified argument is not {@code null},
+ * throwing a NPE exception otherwise.
+ *
+ *
The message of the exception is {@code errorMessage}.
+ *
+ * @param the object type
+ * @param obj the object to check
+ * @param errorMessage the message associated with the NPE
+ * @return the validated object
+ * @throws NullPointerException if the object is {@code null}
+ * @see #checkNotNull(Object, String, Object...)
+ */
+ public static T checkNotNull(final T obj,
+ final Object errorMessage) {
+ if (obj == null) {
+ throw new NullPointerException(String.valueOf(errorMessage));
+ }
+ return obj;
+ }
+
+ /**
+ * Preconditions that the specified argument is not {@code null},
+ * throwing a NPE exception otherwise.
+ *
+ *
The message of the exception is {@code String.format(f, m)}.
+ *
+ * @param the object type
+ * @param obj the object to check
+ * @param message the {@link String#format(String, Object...)}
+ * exception message if valid. Otherwise,
+ * the message is {@link #VALIDATE_IS_NOT_NULL_EX_MESSAGE}
+ * @param values the optional values for the formatted exception message
+ * @return the validated object
+ * @throws NullPointerException if the object is {@code null}
+ * @see #checkNotNull(Object, Supplier)
+ */
+ public static T checkNotNull(final T obj, final String message,
+ final Object... values) {
+ // Deferring the evaluation of the message is a tradeoff between the cost
+ // of constructing lambda Vs constructing a string object.
+ // Using lambda would allocate an object on every call:
+ // return checkNotNull(obj, () -> String.format(message, values));
+ if (obj == null) {
+ String msg;
+ try {
+ msg = String.format(message, values);
+ } catch (Exception e) {
+ LOG.debug("Error formatting message", e);
+ msg = VALIDATE_IS_NOT_NULL_EX_MESSAGE;
+ }
+ throw new NullPointerException(msg);
+ }
+ return obj;
+ }
+
+ /**
+ * Preconditions that the specified argument is not {@code null},
+ * throwing a NPE exception otherwise.
+ *
+ *
The message of the exception is {@code msgSupplier.get()}.
+ *
+ * @param the object type
+ * @param obj the object to check
+ * @param msgSupplier the {@link Supplier#get()} set the
+ * exception message if valid. Otherwise,
+ * the message is {@link #VALIDATE_IS_NOT_NULL_EX_MESSAGE}
+ * @return the validated object (never {@code null} for method chaining)
+ * @throws NullPointerException if the object is {@code null}
+ */
+ public static T checkNotNull(final T obj,
+ final Supplier msgSupplier) {
+ if (obj == null) {
+ String msg;
+ try {
+ // note that we can get NPE evaluating the message itself;
+ // but we do not want this to override the actual NPE.
+ msg = msgSupplier.get();
+ } catch (Exception e) {
+ // ideally we want to log the error to capture. This may cause log files
+ // to bloat. On the other hand, swallowing the exception may hide a bug
+ // in the caller. Debug level is a good compromise between the two
+ // concerns.
+ LOG.debug("Error formatting message", e);
+ msg = VALIDATE_IS_NOT_NULL_EX_MESSAGE;
+ }
+ throw new NullPointerException(msg);
+ }
+ return obj;
+ }
+
+ /* @VisibleForTesting */
+ static String getDefaultNullMSG() {
+ return VALIDATE_IS_NOT_NULL_EX_MESSAGE;
+ }
+}
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestPreconditions.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestPreconditions.java
new file mode 100644
index 0000000000..7feffc3163
--- /dev/null
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestPreconditions.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.util;
+
+import org.junit.Test;
+
+import org.apache.hadoop.test.LambdaTestUtils;
+
+public class TestPreconditions {
+ private static final String NON_NULL_STRING = "NON_NULL_OBJECT";
+ private static final String NON_INT_STRING = "NOT_INT";
+ private static final String EXPECTED_ERROR_MSG = "Expected-Error-MSG";
+ private static final String EXPECTED_ERROR_MSG_ARGS =
+ EXPECTED_ERROR_MSG + " %s number %d";
+ private static final String NULL_FORMATTER = null;
+
+ private String errorMessage;
+
+ @Test
+ public void testCheckNotNullSuccess() {
+ Preconditions.checkNotNull(NON_NULL_STRING);
+ // null supplier
+ Preconditions.checkNotNull(NON_NULL_STRING, null);
+ // ill-formated string supplier
+ Preconditions.checkNotNull(NON_NULL_STRING, ()-> String.format("%d",
+ NON_INT_STRING));
+ // null pattern to string formatter
+ Preconditions.checkNotNull(NON_NULL_STRING, NULL_FORMATTER, null, 1);
+ // null arguments to string formatter
+ Preconditions.checkNotNull(NON_NULL_STRING, EXPECTED_ERROR_MSG_ARGS,
+ null, null);
+ // illegal format exception
+ Preconditions.checkNotNull(NON_NULL_STRING, "message %d %d",
+ NON_INT_STRING, 1);
+ // insufficient arguments
+ Preconditions.checkNotNull(NON_NULL_STRING, EXPECTED_ERROR_MSG_ARGS,
+ NON_INT_STRING);
+ // null format in string supplier
+ Preconditions.checkNotNull(NON_NULL_STRING,
+ () -> String.format(NULL_FORMATTER, NON_INT_STRING));
+ }
+
+ @Test
+ public void testCheckNotNullFailure() throws Exception {
+ // failure without message
+ LambdaTestUtils.intercept(NullPointerException.class,
+ Preconditions.getDefaultNullMSG(),
+ () -> Preconditions.checkNotNull(null));
+
+ // failure with message
+ errorMessage = EXPECTED_ERROR_MSG;
+ LambdaTestUtils.intercept(NullPointerException.class,
+ errorMessage,
+ () -> Preconditions.checkNotNull(null, errorMessage));
+
+ // failure with Null message
+ LambdaTestUtils.intercept(NullPointerException.class,
+ null,
+ () -> Preconditions.checkNotNull(null, errorMessage));
+
+ // failure with message format
+ errorMessage = EXPECTED_ERROR_MSG + " %s";
+ String arg = "NPE";
+ String expectedMSG = String.format(errorMessage, arg);
+ LambdaTestUtils.intercept(NullPointerException.class,
+ expectedMSG,
+ () -> Preconditions.checkNotNull(null, errorMessage, arg));
+
+ // failure with multiple arg message format
+ errorMessage = EXPECTED_ERROR_MSG_ARGS;
+ expectedMSG =
+ String.format(errorMessage, arg, 1);
+ LambdaTestUtils.intercept(NullPointerException.class,
+ expectedMSG,
+ () -> Preconditions.checkNotNull(null, errorMessage, arg, 1));
+
+ // illegal format will be thrown if the case is not handled correctly
+ LambdaTestUtils.intercept(NullPointerException.class,
+ Preconditions.getDefaultNullMSG(),
+ () -> Preconditions.checkNotNull(null,
+ errorMessage, 1, NON_INT_STRING));
+
+ // illegal format will be thrown for insufficient Insufficient Args
+ LambdaTestUtils.intercept(NullPointerException.class,
+ Preconditions.getDefaultNullMSG(),
+ () -> Preconditions.checkNotNull(null, errorMessage, NON_NULL_STRING));
+
+ // illegal format in supplier
+ LambdaTestUtils.intercept(NullPointerException.class,
+ Preconditions.getDefaultNullMSG(),
+ () -> Preconditions.checkNotNull(null,
+ () -> String.format(errorMessage, 1, NON_INT_STRING)));
+
+ // insufficient arguments in string Supplier
+ LambdaTestUtils.intercept(NullPointerException.class,
+ Preconditions.getDefaultNullMSG(),
+ () -> Preconditions.checkNotNull(null,
+ () -> String.format(errorMessage, NON_NULL_STRING)));
+
+ // null formatter
+ LambdaTestUtils.intercept(NullPointerException.class,
+ Preconditions.getDefaultNullMSG(),
+ () -> Preconditions.checkNotNull(null,
+ () -> String.format(NULL_FORMATTER, NON_NULL_STRING)));
+ }
+}