All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.flink.util.ExceptionUtils Maven / Gradle / Ivy

There is a newer version: 1.5.1
Show newest version
/*
 * 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.
 */

//
// The function "stringifyException" is based on source code from the Hadoop Project (http://hadoop.apache.org/),
// licensed by the Apache Software Foundation (ASF) under the Apache License, Version 2.0.
// See the NOTICE file distributed with this work for additional information regarding copyright ownership.
//

package org.apache.flink.util;

import org.apache.flink.annotation.Internal;
import org.apache.flink.util.function.RunnableWithException;

import javax.annotation.Nullable;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Optional;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.function.Predicate;

import static org.apache.flink.util.Preconditions.checkNotNull;

/**
 * A collection of utility functions for dealing with exceptions and exception workflows.
 */
@Internal
public final class ExceptionUtils {

	/** The stringified representation of a null exception reference. */
	public static final String STRINGIFIED_NULL_EXCEPTION = "(null)";

	/**
	 * Makes a string representation of the exception's stack trace, or "(null)", if the
	 * exception is null.
	 *
	 * 

This method makes a best effort and never fails. * * @param e The exception to stringify. * @return A string with exception name and call stack. */ public static String stringifyException(final Throwable e) { if (e == null) { return STRINGIFIED_NULL_EXCEPTION; } try { StringWriter stm = new StringWriter(); PrintWriter wrt = new PrintWriter(stm); e.printStackTrace(wrt); wrt.close(); return stm.toString(); } catch (Throwable t) { return e.getClass().getName() + " (error while printing stack trace)"; } } /** * Unpacks an specified exception and returns its cause. Otherwise the given * {@link Throwable} is returned. * * @param throwableToStrip to strip * @param typeToStrip type to strip * @return Unpacked cause or given Throwable if not packed */ public static Throwable stripException(Throwable throwableToStrip, Class typeToStrip) { while (typeToStrip.isAssignableFrom(throwableToStrip.getClass()) && throwableToStrip.getCause() != null) { throwableToStrip = throwableToStrip.getCause(); } return throwableToStrip; } /** * Checks whether the given exception indicates a situation that may leave the * JVM in a corrupted state, meaning a state where continued normal operation can only be * guaranteed via clean process restart. * *

Currently considered fatal exceptions are Virtual Machine errors indicating * that the JVM is corrupted, like {@link InternalError}, {@link UnknownError}, * and {@link java.util.zip.ZipError} (a special case of InternalError). * The {@link ThreadDeath} exception is also treated as a fatal error, because when * a thread is forcefully stopped, there is a high chance that parts of the system * are in an inconsistent state. * * @param t The exception to check. * @return True, if the exception is considered fatal to the JVM, false otherwise. */ public static boolean isJvmFatalError(Throwable t) { return (t instanceof InternalError) || (t instanceof UnknownError) || (t instanceof ThreadDeath); } /** * Checks whether the given exception indicates a situation that may leave the * JVM in a corrupted state, or an out-of-memory error. * *

See {@link ExceptionUtils#isJvmFatalError(Throwable)} for a list of fatal JVM errors. * This method additionally classifies the {@link OutOfMemoryError} as fatal, because it * may occur in any thread (not the one that allocated the majority of the memory) and thus * is often not recoverable by destroying the particular thread that threw the exception. * * @param t The exception to check. * @return True, if the exception is fatal to the JVM or and OutOfMemoryError, false otherwise. */ public static boolean isJvmFatalOrOutOfMemoryError(Throwable t) { return isJvmFatalError(t) || t instanceof OutOfMemoryError; } /** * Rethrows the given {@code Throwable}, if it represents an error that is fatal to the JVM. * See {@link ExceptionUtils#isJvmFatalError(Throwable)} for a definition of fatal errors. * * @param t The Throwable to check and rethrow. */ public static void rethrowIfFatalError(Throwable t) { if (isJvmFatalError(t)) { throw (Error) t; } } /** * Rethrows the given {@code Throwable}, if it represents an error that is fatal to the JVM * or an out-of-memory error. See {@link ExceptionUtils#isJvmFatalError(Throwable)} for a * definition of fatal errors. * * @param t The Throwable to check and rethrow. */ public static void rethrowIfFatalErrorOrOOM(Throwable t) { if (isJvmFatalError(t) || t instanceof OutOfMemoryError) { throw (Error) t; } } /** * Adds a new exception as a {@link Throwable#addSuppressed(Throwable) suppressed exception} * to a prior exception, or returns the new exception, if no prior exception exists. * *

{@code
	 *
	 * public void closeAllThings() throws Exception {
	 *     Exception ex = null;
	 *     try {
	 *         component.shutdown();
	 *     } catch (Exception e) {
	 *         ex = firstOrSuppressed(e, ex);
	 *     }
	 *     try {
	 *         anotherComponent.stop();
	 *     } catch (Exception e) {
	 *         ex = firstOrSuppressed(e, ex);
	 *     }
	 *     try {
	 *         lastComponent.shutdown();
	 *     } catch (Exception e) {
	 *         ex = firstOrSuppressed(e, ex);
	 *     }
	 *
	 *     if (ex != null) {
	 *         throw ex;
	 *     }
	 * }
	 * }
* * @param newException The newly occurred exception * @param previous The previously occurred exception, possibly null. * * @return The new exception, if no previous exception exists, or the previous exception with the * new exception in the list of suppressed exceptions. */ public static T firstOrSuppressed(T newException, @Nullable T previous) { checkNotNull(newException, "newException"); if (previous == null) { return newException; } else { previous.addSuppressed(newException); return previous; } } /** * Throws the given {@code Throwable} in scenarios where the signatures do not allow you to * throw an arbitrary Throwable. Errors and RuntimeExceptions are thrown directly, other exceptions * are packed into runtime exceptions * * @param t The throwable to be thrown. */ public static void rethrow(Throwable t) { if (t instanceof Error) { throw (Error) t; } else if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new RuntimeException(t); } } /** * Throws the given {@code Throwable} in scenarios where the signatures do not allow you to * throw an arbitrary Throwable. Errors and RuntimeExceptions are thrown directly, other exceptions * are packed into a parent RuntimeException. * * @param t The throwable to be thrown. * @param parentMessage The message for the parent RuntimeException, if one is needed. */ public static void rethrow(Throwable t, String parentMessage) { if (t instanceof Error) { throw (Error) t; } else if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new RuntimeException(parentMessage, t); } } /** * Throws the given {@code Throwable} in scenarios where the signatures do allow to * throw a Exception. Errors and Exceptions are thrown directly, other "exotic" * subclasses of Throwable are wrapped in an Exception. * * @param t The throwable to be thrown. * @param parentMessage The message for the parent Exception, if one is needed. */ public static void rethrowException(Throwable t, String parentMessage) throws Exception { if (t instanceof Error) { throw (Error) t; } else if (t instanceof Exception) { throw (Exception) t; } else { throw new Exception(parentMessage, t); } } /** * Throws the given {@code Throwable} in scenarios where the signatures do allow to * throw a Exception. Errors and Exceptions are thrown directly, other "exotic" * subclasses of Throwable are wrapped in an Exception. * * @param t The throwable to be thrown. */ public static void rethrowException(Throwable t) throws Exception { if (t instanceof Error) { throw (Error) t; } else if (t instanceof Exception) { throw (Exception) t; } else { throw new Exception(t.getMessage(), t); } } /** * Tries to throw the given {@code Throwable} in scenarios where the signatures allows only IOExceptions * (and RuntimeException and Error). Throws this exception directly, if it is an IOException, * a RuntimeException, or an Error. Otherwise does nothing. * * @param t The Throwable to be thrown. */ public static void tryRethrowIOException(Throwable t) throws IOException { if (t instanceof IOException) { throw (IOException) t; } else if (t instanceof RuntimeException) { throw (RuntimeException) t; } else if (t instanceof Error) { throw (Error) t; } } /** * Re-throws the given {@code Throwable} in scenarios where the signatures allows only IOExceptions * (and RuntimeException and Error). * *

Throws this exception directly, if it is an IOException, a RuntimeException, or an Error. Otherwise it * wraps it in an IOException and throws it. * * @param t The Throwable to be thrown. */ public static void rethrowIOException(Throwable t) throws IOException { if (t instanceof IOException) { throw (IOException) t; } else if (t instanceof RuntimeException) { throw (RuntimeException) t; } else if (t instanceof Error) { throw (Error) t; } else { throw new IOException(t.getMessage(), t); } } /** * Checks whether a throwable chain contains a specific type of exception and returns it. * * @param throwable the throwable chain to check. * @param searchType the type of exception to search for in the chain. * @return Optional throwable of the requested type if available, otherwise empty */ public static Optional findThrowable(Throwable throwable, Class searchType) { if (throwable == null || searchType == null) { return Optional.empty(); } Throwable t = throwable; while (t != null) { if (searchType.isAssignableFrom(t.getClass())) { return Optional.of(searchType.cast(t)); } else { t = t.getCause(); } } return Optional.empty(); } /** * Checks whether a throwable chain contains an exception matching a predicate and returns it. * * @param throwable the throwable chain to check. * @param predicate the predicate of the exception to search for in the chain. * @return Optional throwable of the requested type if available, otherwise empty */ public static Optional findThrowable(Throwable throwable, Predicate predicate) { if (throwable == null || predicate == null) { return Optional.empty(); } Throwable t = throwable; while (t != null) { if (predicate.test(t)) { return Optional.of(t); } else { t = t.getCause(); } } return Optional.empty(); } /** * Checks whether a throwable chain contains a specific error message and returns the corresponding throwable. * * @param throwable the throwable chain to check. * @param searchMessage the error message to search for in the chain. * @return Optional throwable containing the search message if available, otherwise empty */ public static Optional findThrowableWithMessage(Throwable throwable, String searchMessage) { if (throwable == null || searchMessage == null) { return Optional.empty(); } Throwable t = throwable; while (t != null) { if (t.getMessage().contains(searchMessage)) { return Optional.of(t); } else { t = t.getCause(); } } return Optional.empty(); } /** * Unpacks an {@link ExecutionException} and returns its cause. Otherwise the given * Throwable is returned. * * @param throwable to unpack if it is an ExecutionException * @return Cause of ExecutionException or given Throwable */ public static Throwable stripExecutionException(Throwable throwable) { while (throwable instanceof ExecutionException && throwable.getCause() != null) { throwable = throwable.getCause(); } return throwable; } /** * Unpacks an {@link CompletionException} and returns its cause. Otherwise the given * Throwable is returned. * * @param throwable to unpack if it is an CompletionException * @return Cause of CompletionException or given Throwable */ public static Throwable stripCompletionException(Throwable throwable) { while (throwable instanceof CompletionException && throwable.getCause() != null) { throwable = throwable.getCause(); } return throwable; } /** * Tries to find a {@link SerializedThrowable} as the cause of the given throwable and throws its * deserialized value. If there is no such throwable, then the original throwable is thrown. * * @param throwable to check for a SerializedThrowable * @param classLoader to be used for the deserialization of the SerializedThrowable * @throws Throwable either the deserialized throwable or the given throwable */ public static void tryDeserializeAndThrow(Throwable throwable, ClassLoader classLoader) throws Throwable { Throwable current = throwable; while (!(current instanceof SerializedThrowable) && current.getCause() != null) { current = current.getCause(); } if (current instanceof SerializedThrowable) { throw ((SerializedThrowable) current).deserializeError(classLoader); } else { throw throwable; } } /** * Checks whether the given exception is a {@link InterruptedException} and sets * the interrupted flag accordingly. * * @param e to check whether it is an {@link InterruptedException} */ public static void checkInterrupted(Throwable e) { if (e instanceof InterruptedException) { Thread.currentThread().interrupt(); } } // ------------------------------------------------------------------------ // Lambda exception utilities // ------------------------------------------------------------------------ public static void suppressExceptions(RunnableWithException action) { try { action.run(); } catch (InterruptedException e) { // restore interrupted state Thread.currentThread().interrupt(); } catch (Throwable t) { if (isJvmFatalError(t)) { rethrow(t); } } } // ------------------------------------------------------------------------ /** Private constructor to prevent instantiation. */ private ExceptionUtils() {} }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy