/* * 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 java.lang; import java.lang.reflect.Field; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import javax.xml.bind.annotation.XmlTransient; /** * {@code Exception} is the superclass of all classes that represent recoverable * exceptions. When exceptions are thrown, they may be caught by application * code. * * @see Throwable * @see Error * @see RuntimeException */ public class Exception extends Throwable { private static final long serialVersionUID = -3387516993124229948L; private transient Reference<Class<?>>[] classContext = null; /** * Constructs a new {@code Exception} that includes the current stack trace. */ public Exception() { super(); initClassContext(); } /** * Constructs a new {@code Exception} with the current stack trace and the * specified detail message. * * @param detailMessage * the detail message for this exception. */ public Exception(String detailMessage) { super(detailMessage); initClassContext(); } /** * Constructs a new {@code Exception} with the current stack trace, the * specified detail message and the specified cause. * * @param detailMessage * the detail message for this exception. * @param throwable * the cause of this exception. */ public Exception(String detailMessage, Throwable throwable) { super(detailMessage, throwable); initClassContext(); } /** * Constructs a new {@code Exception} with the current stack trace and the * specified cause. * * @param throwable * the cause of this exception. */ public Exception(Throwable throwable) { super(throwable); initClassContext(); } /** * Constructs a new exception with the specified detail message, * cause, suppression enabled or disabled, and writable stack * trace enabled or disabled. * * @param message the detail message. * @param cause the cause. (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @param enableSuppression whether or not suppression is enabled * or disabled * @param writableStackTrace whether or not the stack trace should * be writable */ protected Exception(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { try { Field field = null; if (writableStackTrace) { fillInStackTrace(); } else { field = Throwable.class.getDeclaredField("stackTrace"); field.setAccessible(true); field.set(this, null); } field = Throwable.class.getDeclaredField("detailMessage"); field.setAccessible(true); field.set(this, message); field = Throwable.class.getDeclaredField("cause"); field.setAccessible(true); field.set(this, cause); if (!enableSuppression) { field = Throwable.class.getDeclaredField("suppressedExceptions"); field.setAccessible(true); field.set(this, null); } } catch (Exception e) { e.printStackTrace(); } initClassContext(); } @XmlTransient @Deprecated public Class[] getClassContext() { Class<?>[] context = null; if (classContext != null) { context = new Class<?>[classContext.length]; for (int i = 0; i < classContext.length; i++) { Class<?> c = classContext[i].get(); context[i] = c == null ? Object.class : c; } } return context; } @SuppressWarnings("unchecked") private void initClassContext() { Class[] context = SecurityManagerEx.getInstance().getThrowableContext(this); if (context != null) { classContext = new Reference[context.length]; for (int i = 0; i < context.length; i++) { classContext[i] = new WeakReference<Class<?>>(context[i]); } } } protected Class[] classContext() { Class<?>[] context = new Class<?>[classContext.length]; for (int i = 0; i < classContext.length; i++) { Class<?> c = classContext[i].get(); context[i] = c == null ? Object.class : c; } return context; } private static class SecurityManagerEx extends SecurityManager { private static SecurityManagerEx sm; public static SecurityManagerEx getInstance() { // No synchronized block because we don't really care // if multiple instances are created at some point if (sm == null) { sm = new SecurityManagerEx(); } return sm; } public Class[] getThrowableContext(Throwable t) { try { Class[] context = getClassContext(); int nb = 0; for (;;) { if (context[context.length - 1 - nb] == t.getClass()) { break; } nb++; } Class[] nc = new Class[nb]; System.arraycopy(context, context.length - nb, nc, 0, nb); return nc; } catch (Exception e) { return null; } } } }