JDK1.8源码阅读(5)--ThreadLocal/Enum/Throwable

JDK1.8源码阅读(5)–ThreadLocal/Enum/Throwable

一.ThreadLocal类

类图:在这里插入图片描述
这个类并没有继承其他的类或接口。

private final int threadLocalHashCode = nextHashCode(); 原始种子,由内置种子计算而来,用来生成均匀的索引
一个线程可以有多个ThreadLocal实例,各实例之内的原始种子值不相同
一个ThreadLocal实例也可被多个线程共享,此时多个线程内看到的原始种子值是相同的

private static AtomicInteger nextHashCode =new AtomicInteger(); 内置种子,由所有ThreadLocal共享,但每次构造一个ThreadLocal实例,其值都会更新,可以理解为每一个ThreadLocal都具有唯一的标识。

private static final int HASH_INCREMENT = 0x61c88647; 哈希魔数 用来生成伪随机数

private static int nextHashCode() 生成下一个哈希值,根据哈希魔数伪随机生成哈希值

    private static int nextHashCode() {
        return nextHashCode.getAndAdd(HASH_INCREMENT);
    }

protected T initialValue() 初始化值,由子类重写

public static ThreadLocal withInitial(Supplier<? extends S> supplier)
返回一个扩展的ThreadLocal,其关联的初值由supplier给出

    public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
        return new SuppliedThreadLocal<>(supplier);
    }

public ThreadLocal() {} 构造函数

static class ThreadLocalMap 定义了储存数据的结构和方法

    static class ThreadLocalMap {
        static class Entry extends WeakReference<ThreadLocal<?>> {
			//保存与ThreadLocal关联的那个值
            Object value; 
            //构造Entry函数,将数据存入Entry,相当于hashMap
            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }
         *  初始容量 - 必须是二的幂。
        private static final int INITIAL_CAPACITY = 16;
         *  该表,必要时调整大小。 table.length必须总是2的幂。
        private Entry[] table;

         *  表中的条目数。
        private int size = 0;

        private int threshold; // Default to 0
        
         *  设置调整大小阈值以保持最差2/3的负载系数。

        private void setThreshold(int len) {
            threshold = len * 2 / 3;
        }
//后一个值
        private static int nextIndex(int i, int len) {
            return ((i + 1 < len) ? i + 1 : 0);
        }
//前一个值
        private static int prevIndex(int i, int len) {
            return ((i - 1 >= 0) ? i - 1 : len - 1);
        }

		//构造函数,生成table初始容量16
        ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
            table = new Entry[INITIAL_CAPACITY];
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }
		//构造函数,参数也是ThreadLocalMap,将原来的Map复制一下
        private ThreadLocalMap(ThreadLocalMap parentMap) {
            Entry[] parentTable = parentMap.table;
            int len = parentTable.length;
            setThreshold(len);
            table = new Entry[len];

            for (int j = 0; j < len; j++) {
                Entry e = parentTable[j];
                if (e != null) {
                    @SuppressWarnings("unchecked")
                    ThreadLocal<Object> key = (ThreadLocal<Object>) e.get();
                    if (key != null) {
                        Object value = key.childValue(e.value);
                        Entry c = new Entry(key, value);
                        int h = key.threadLocalHashCode & (len - 1);
                        while (table[h] != null)
                            h = nextIndex(h, len);
                        table[h] = c;
                        size++;
                    }
                }
            }
        }

		//根据key值得到Entry,如果在匹配位置拿不到正确的Entry,就到其附近的位置进行寻找
        private Entry getEntry(ThreadLocal<?> key) {
            int i = key.threadLocalHashCode & (table.length - 1);
            Entry e = table[i];
            if (e != null && e.get() == key)
                return e;
            else
                return getEntryAfterMiss(key, i, e);
        }

		//在附近的位置寻找匹配的值,顺便清理垃圾值
        private Entry getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e) {
            Entry[] tab = table;
            int len = tab.length;

            while (e != null) {
                ThreadLocal<?> k = e.get();
                if (k == key)
                    return e;
                if (k == null)
                    expungeStaleEntry(i);
                else
                    i = nextIndex(i, len);
                e = tab[i];
            }
            return null;
        }

        //设置key和value,
        private void set(ThreadLocal<?> key, Object value) {

            // We don't use a fast path as with get() because it is at
            // least as common to use set() to create new entries as
            // it is to replace existing ones, in which case, a fast
            // path would fail more often than not.

            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);

            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                ThreadLocal<?> k = e.get();

                if (k == key) {
                    e.value = value;
                    return;
                }

                if (k == null) {
                    replaceStaleEntry(key, value, i);
                    return;
                }
            }

            tab[i] = new Entry(key, value);
            int sz = ++size;
            if (!cleanSomeSlots(i, sz) && sz >= threshold)
                rehash();
        }

        /**
         * Remove the entry for key.
         * <p>
         *  删除密钥的条目。删除了清理下垃圾值
         * 
         */
        private void remove(ThreadLocal<?> key) {                                                                                      
            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);
            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                if (e.get() == key) {
                    e.clear();
                    expungeStaleEntry(i);
                    return;
                }
            }
        }

 //将垃圾值赋新值
        private void replaceStaleEntry(ThreadLocal<?> key, Object value,
                                       int staleSlot) {
            Entry[] tab = table;
            int len = tab.length;
            Entry e;
            int slotToExpunge = staleSlot;
            for (int i = prevIndex(staleSlot, len);
                 (e = tab[i]) != null;
                 i = prevIndex(i, len))
                if (e.get() == null)
                    slotToExpunge = i;
            for (int i = nextIndex(staleSlot, len);
                 (e = tab[i]) != null;
                 i = nextIndex(i, len)) {
                ThreadLocal<?> k = e.get();

                if (k == key) {
                    e.value = value;

                    tab[i] = tab[staleSlot];
                    tab[staleSlot] = e;

                    // Start expunge at preceding stale entry if it exists
                    if (slotToExpunge == staleSlot)
                        slotToExpunge = i;
                    cleanSomeSlots(expungeStaleEntry(slotToExpunge), len);
                    return;
                }

                if (k == null && slotToExpunge == staleSlot)
                    slotToExpunge = i;
            }

          
            tab[staleSlot].value = null;
            tab[staleSlot] = new Entry(key, value);

   
            if (slotToExpunge != staleSlot)
                cleanSomeSlots(expungeStaleEntry(slotToExpunge), len);
        }
        
         //首先清理位于staleSlot的垃圾值,而后向后遍历(一直遍历到第一个空位置位置),在遍历过程中如果当前位置是个垃圾值就清理,不是垃圾值检测这个值是不是在正确的位置上,如果不在就移动到他应该在的位置(如果应该在的位置有值,就移动到最近的那个位置)
        private int expungeStaleEntry(int staleSlot) {
            Entry[] tab = table;
            int len = tab.length;

            // expunge entry at staleSlot
            tab[staleSlot].value = null;
            tab[staleSlot] = null;
            size--;

            // Rehash until we encounter null
            Entry e;
            int i;
            for (i = nextIndex(staleSlot, len);
                 (e = tab[i]) != null;
                 i = nextIndex(i, len)) {
                ThreadLocal<?> k = e.get();
                if (k == null) {
                    e.value = null;
                    tab[i] = null;
                    size--;
                } else {
                    int h = k.threadLocalHashCode & (len - 1);
                    if (h != i) {
                        tab[i] = null;

                        // Unlike Knuth 6.4 Algorithm R, we must scan until
                        // null because multiple entries could have been stale.
                        while (tab[h] != null)
                            h = nextIndex(h, len);
                        tab[h] = e;
                    }
                }
            }
            return i;
        }

		//清理槽位,从下标i开始向后遍历,清理一部分垃圾值,清理过后元素依然是紧凑的
        private boolean cleanSomeSlots(int i, int n) {
            boolean removed = false;
            Entry[] tab = table;
            int len = tab.length;
            do {
                i = nextIndex(i, len);
                Entry e = tab[i];
                if (e != null && e.get() == null) {
                    n = len;
                    removed = true;
                    i = expungeStaleEntry(i);
                }
            } while ( (n >>>= 1) != 0);
            return removed;
        }


         * 重新包装和/或重新调整桌子的尺寸。首先扫描整个表,删除过时的条目。如果这不足以缩小表的大小,请将表大小加倍。
        private void rehash() {
            expungeStaleEntries();

            // Use lower threshold for doubling to avoid hysteresis
            if (size >= threshold - threshold / 4)
                resize();
        }

        /**
         * Double the capacity of the table.
         * <p>
         *  加倍表的容量。
         * 
         */
        private void resize() {
            Entry[] oldTab = table;
            int oldLen = oldTab.length;
            int newLen = oldLen * 2;
            Entry[] newTab = new Entry[newLen];
            int count = 0;

            for (int j = 0; j < oldLen; ++j) {
                Entry e = oldTab[j];
                if (e != null) {
                    ThreadLocal<?> k = e.get();
                    if (k == null) {
                        e.value = null; // Help the GC
                    } else {
                        int h = k.threadLocalHashCode & (newLen - 1);
                        while (newTab[h] != null)
                            h = nextIndex(h, newLen);
                        newTab[h] = e;
                        count++;
                    }
                }
            }

            setThreshold(newLen);
            size = count;
            table = newTab;
        }

        /**
         * Expunge all stale entries in the table.
         * <p>
         *  清除表中所有失效的条目。
         */
        private void expungeStaleEntries() {
            Entry[] tab = table;
            int len = tab.length;
            for (int j = 0; j < len; j++) {
                Entry e = tab[j];
                if (e != null && e.get() == null)
                    expungeStaleEntry(j);
            }
        }
    }

public T get()

    public T get() {
    //首先获取当前线程
        Thread t = Thread.currentThread();
        //获取Map
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

private T setInitialValue() 初始化map

    private T setInitialValue() {
    //value是被子类重写的初始化方法生成的值
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }

public void set(T value) 设置值

public void remove() 移除值

ThreadLocalMap getMap(Thread t) 返回的是ThreadLocal类中的静态变量,所有线程公用

void createMap(Thread t, T firstValue) 生成新表

static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) 复制旧表

T childValue(T parentValue) 获取parentValue,有时会对其进行加工,主要用于测试,参见子类InheritableThreadLocal等。

static final class SuppliedThreadLocal extends ThreadLocal ThreadLocal的一个扩展。其ThreadLocal关联的初值由字段supplier给出

    static final class SuppliedThreadLocal<T> extends ThreadLocal<T> {

        private final Supplier<? extends T> supplier;

        SuppliedThreadLocal(Supplier<? extends T> supplier) {
            this.supplier = Objects.requireNonNull(supplier);
        }

        @Override
        protected T initialValue() {
            return supplier.get();
        }
    }

二.Enum类

类图:
在这里插入图片描述
枚举类继承了Serializable接口跟Comparable接口
在这里插入图片描述

  • 示例:
  • public enum Color {
  • WHITE, BLACK 
    
  • }
  • 等价于:
  • public final class Color extends Enum {
  • public static final Color WHITE = new Color(“WHITE”, 0);
  • public static final Color BLACK = new Color(“BLACK”, 1);
  • public Color(String name, int ordinal) {
  •   super(name, ordinal);
    
  • }
    private static final long serialVersionUID = 1L; 序列号
    private final String name; 常量名称,不可以修改
    public final String name() 得到枚举类的名称
    private final int ordinal; 枚举实例的值
    public final int ordinal() 返回枚举实例的值
    protected Enum(String name, int ordinal) 构造函数,传入名称和值
    public String toString() 重写toString方法,返回名称
    public final boolean equals(Object other) 判等方法跟==相同
    public final int hashCode() 返回Object类的hashCode值
    protected final Object clone() 不允许复制
    public final int compareTo(E o) 重写Comparable接口,比较ordinal值
    public final Class getDeclaringClass() 返回枚举类类对象
    public final Class<E> getDeclaringClass() {
        Class<?> clazz = getClass();
        Class<?> zuper = clazz.getSuperclass();
        return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
    }

protected final void finalize() 枚举类不能有finalize方法

public static <T extends Enum> T valueOf(Class enumType,String name)

    public static <T extends Enum<T>> T valueOf(Class<T> enumType,
                                                String name) {
        T result = enumType.enumConstantDirectory().get(name);
        if (result != null)
            return result;
        if (name == null)
            throw new NullPointerException("Name is null");
        throw new IllegalArgumentException(
            "No enum constant " + enumType.getCanonicalName() + "." + name);
    }

三.Throwable类

异常类,异常体系的祖先
类图:在这里插入图片描述
只继承了Serializable接口
private static final long serialVersionUID = -3042686055658047285L; 序列号
private transient Object backtrace; 本地代码保存了在这个槽中的堆栈回溯的一些指示。
private String detailMessage; 具体细节信息
private static class SentinelHolder Holder类,用于延迟初始化只用于序列化的哨兵对象。

private static class SentinelHolder {
		//将堆栈跟踪设置为包含此sentinel值的一个单元数组,表示未来尝试设置堆栈跟踪将被忽略。
        public static final StackTraceElement STACK_TRACE_ELEMENT_SENTINEL =
            new StackTraceElement("", "", null, Integer.MIN_VALUE);

         *  在串行形式中使用的哨兵值,用于指示不可变的堆栈跟踪。
        public static final StackTraceElement[] STACK_TRACE_SENTINEL =
            new StackTraceElement[] {STACK_TRACE_ELEMENT_SENTINEL};
    }

private static final StackTraceElement[] UNASSIGNED_STACK = new StackTraceElement[0]; 初始化一个共享的空栈
插播一个StackTraceElement类:

//正常来讲这个类的初始化是由JVM来完成的,在JDK5之后将这个方法设为public
public final class StackTraceElement implements java.io.Serializable {
    // Normally initialized by VM (public constructor added in 1.5)
    //私有变量,类名
    private String declaringClass;
    //方法名称
    private String methodName;
    //文件夹名称
    private String fileName;
	//行数    
    private int    lineNumber;
	//构造函数
    public StackTraceElement(String declaringClass, String methodName,
                             String fileName, int lineNumber) {
        this.declaringClass = Objects.requireNonNull(declaringClass, "Declaring class is null");
        this.methodName     = Objects.requireNonNull(methodName, "Method name is null");
        this.fileName       = fileName;
        this.lineNumber     = lineNumber;
    }

    public String getFileName() {
        return fileName;
    }

    public int getLineNumber() {
        return lineNumber;
    }

    public String getClassName() {
        return declaringClass;
    }

    public String getMethodName() {
        return methodName;
    }
	//这个栈帧是不是运行在本地方法上的
    public boolean isNativeMethod() {
        return lineNumber == -2;
    }
		//重写object的toString方法
    public String toString() {
        return getClassName() + "." + methodName +
            (isNativeMethod() ? "(Native Method)" :
             (fileName != null && lineNumber >= 0 ?
              "(" + fileName + ":" + lineNumber + ")" :
              (fileName != null ?  "("+fileName+")" : "(Unknown Source)")));
    }
	//判等
    public boolean equals(Object obj) {
        if (obj==this)
            return true;
        if (!(obj instanceof StackTraceElement))
            return false;
        StackTraceElement e = (StackTraceElement)obj;
        return e.declaringClass.equals(declaringClass) &&
            e.lineNumber == lineNumber &&
            Objects.equals(methodName, e.methodName) &&
            Objects.equals(fileName, e.fileName);
    }

    /**
     * Returns a hash code value for this stack trace element.
     */
    public int hashCode() {
        int result = 31*declaringClass.hashCode() + methodName.hashCode();
        result = 31*result + Objects.hashCode(fileName);
        result = 31*result + lineNumber;
        return result;
    }

    private static final long serialVersionUID = 6992337162326171013L;
}

private Throwable cause = this; 将cause赋值为这个实例
private StackTraceElement[] stackTrace = UNASSIGNED_STACK; 将静态变量赋值给实例变量
private static final List SUPPRESSED_SENTINEL =Collections.unmodifiableList(new ArrayList(0));
初始化一个共享的Throwable的集合
private List suppressedExceptions = SUPPRESSED_SENTINEL; 将静态变量赋值给实例的suppressedExceptions
private static final String NULL_CAUSE_MESSAGE = “Cannot suppress a null exception.”; 抑制无错误字段
private static final String SELF_SUPPRESSION_MESSAGE = “Self-suppression not permitted”; 自我抑制字段
private static final String CAUSE_CAPTION = "Caused by: "; 原因标题字段
private static final String SUPPRESSED_CAPTION = "Suppressed: "; 抑制标题字段

public Throwable() 构造函数

    public Throwable() {
        fillInStackTrace();
    }
    //加锁的填充堆栈信息
    public synchronized Throwable fillInStackTrace() {
    //首先判断当前实例的stackTrace是否是空的
        if (stackTrace != null ||
            backtrace != null /* Out of protocol state */ ) {
            fillInStackTrace(0);
            stackTrace = UNASSIGNED_STACK;
        }
        return this;
    }
    private native Throwable fillInStackTrace(int dummy);  //本地方法,填充堆栈信息

public Throwable(String message)
构造函数

    public Throwable(String message) {
        fillInStackTrace();
        detailMessage = message;
    }

public Throwable(String message, Throwable cause)
构造函数

    public Throwable(String message, Throwable cause) {
        fillInStackTrace();
        detailMessage = message;
        this.cause = cause;
    }

public Throwable(Throwable cause)
构造函数

    public Throwable(Throwable cause) {
        fillInStackTrace();
        detailMessage = (cause==null ? null : cause.toString());
        this.cause = cause;
    }

protected Throwable(String message, Throwable cause,boolean enableSuppression,boolean writableStackTrace)
protected函数

    protected Throwable(String message, Throwable cause,
                        boolean enableSuppression,
                        boolean writableStackTrace) {
                        //如果堆栈信息可写就填充堆栈信息,如果不可写就设为null
        if (writableStackTrace) {
            fillInStackTrace();
        } else {
            stackTrace = null;
        }
        detailMessage = message;
        this.cause = cause;
        if (!enableSuppression)
            suppressedExceptions = null;
    }

public String getMessage() 返回细节信息

public String getLocalizedMessage()得到本地信息,就是得到细节信息

public synchronized Throwable getCause()
加锁的返回原因,如果原因是这个实例本身就返回null

    public synchronized Throwable getCause() {
        return (cause==this ? null : cause);
    }

public synchronized Throwable initCause(Throwable cause) 初始化原因

    public synchronized Throwable initCause(Throwable cause) {
    //如果当前实例的原因不等于自身,那么将抛出错误
        if (this.cause != this)
            throw new IllegalStateException("Can't overwrite cause with " +
                                            Objects.toString(cause, "a null"), this);
      //并且参数原因不能等于实例,如果等于将抛出异常
        if (cause == this)
            throw new IllegalArgumentException("Self-causation not permitted", this);
        this.cause = cause;
        return this;
    }

public String toString()
重写Object的toString方法,如果detailmessage是null就返回类的名称,如果不为空返回detailmessage

    public String toString() {
        String s = getClass().getName();
        String message = getLocalizedMessage();
        return (message != null) ? (s + ": " + message) : s;
    }

public void printStackTrace() 打印堆栈信息
先看三个内部抽象类:

//抽象类
    private abstract static class PrintStreamOrWriter {
        /** Returns the object to be locked when using this StreamOrWriter */
        //抽象方法lock
        abstract Object lock();

        /** Prints the specified string as a line on this StreamOrWriter */
        //抽象方法打印
        abstract void println(Object o);
    }
	//包装的打印流,操作字节流
    private static class WrappedPrintStream extends PrintStreamOrWriter {
        private final PrintStream printStream;
		//构造函数
        WrappedPrintStream(PrintStream printStream) {
            this.printStream = printStream;
        }
     //重写了lock方法,返回常量打印流
        Object lock() {
            return printStream;
        }
	//将对象打印出来
        void println(Object o) {
            printStream.println(o);
        }
    }
	//包装过的打印写,操作字符流
    private static class WrappedPrintWriter extends PrintStreamOrWriter {
        private final PrintWriter printWriter;

        WrappedPrintWriter(PrintWriter printWriter) {
            this.printWriter = printWriter;
        }

        Object lock() {
            return printWriter;
        }

        void println(Object o) {
            printWriter.println(o);
        }
    }
    public void printStackTrace() {
        printStackTrace(System.err);
    }
    public void printStackTrace(PrintStream s) {
        printStackTrace(new WrappedPrintStream(s));
    }
    private void printStackTrace(PrintStreamOrWriter s) {
        //创建一个泛型为Throwable的set,使用这样的构造方法,我觉得是用工厂模式希望继承IdentityHashMap的判等特性,就是这个新生成的set中判等不是仅仅值相同就可以,还需要引用相同。
        Set<Throwable> dejaVu =
            Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());
            //将当前实例对象加入到set中
        dejaVu.add(this);
		//将s.lock上锁(就是printStream)
        synchronized (s.lock()) {
            // 打印这个对象的toString信息
            s.println(this);
            //获取堆栈信息
            StackTraceElement[] trace = getOurStackTrace();
            //打印所有的堆栈信息
            for (StackTraceElement traceElement : trace)
                s.println("\tat " + traceElement);
			//打印附加信息
            // Print suppressed exceptions, if any
            for (Throwable se : getSuppressed())
                se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
			//打印原因
            // Print cause, if any
            Throwable ourCause = getCause();
            if (ourCause != null)
                ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
        }
    }
    

private void printEnclosedStackTrace(PrintStreamOrWriter s,StackTraceElement[] enclosingTrace,String caption,String prefix,Set dejaVu)打印附加信息

    private void printEnclosedStackTrace(PrintStreamOrWriter s,
                                         StackTraceElement[] enclosingTrace,
                                         String caption,
                                         String prefix,
                                         Set<Throwable> dejaVu) {
             //断言当前的线程持有printStream的锁
        assert Thread.holdsLock(s.lock());
        //如果set中包含了当前throwable对象
        if (dejaVu.contains(this)) {
            s.println("\t[CIRCULAR REFERENCE:" + this + "]");
        } else {
            dejaVu.add(this);
            // Compute number of frames in common between this and enclosing trace
            //重新获得trace
            StackTraceElement[] trace = getOurStackTrace();
            int m = trace.length - 1;
            int n = enclosingTrace.length - 1;
            while (m >= 0 && n >=0 && trace[m].equals(enclosingTrace[n])) {
                m--; n--;
            }
            //跟不加入当前throwable对象的trace中元素一样的长度
            int framesInCommon = trace.length - 1 - m;

            // Print our stack trace
            s.println(prefix + caption + this);
            for (int i = 0; i <= m; i++)
                s.println(prefix + "\tat " + trace[i]);
            if (framesInCommon != 0)
                s.println(prefix + "\t... " + framesInCommon + " more");

            // Print suppressed exceptions, if any
            for (Throwable se : getSuppressed())
                se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
                                           prefix +"\t", dejaVu);

            // Print cause, if any
            Throwable ourCause = getCause();
            if (ourCause != null)
                ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, prefix, dejaVu);
        }
    }

public StackTraceElement[] getStackTrace() 返回堆栈信息的复制

public StackTraceElement[] getStackTrace() {
        return getOurStackTrace().clone();
    }

private synchronized StackTraceElement[] getOurStackTrace() 返回堆栈信息

    private synchronized StackTraceElement[] getOurStackTrace() {
        // Initialize stack trace field with information from
        // backtrace if this is the first call to this method
        if (stackTrace == UNASSIGNED_STACK ||
            (stackTrace == null && backtrace != null) /* Out of protocol state */) {
            //堆栈深度
            int depth = getStackTraceDepth();
            //初始化stackTrace
            stackTrace = new StackTraceElement[depth];
            for (int i=0; i < depth; i++)
            //获取每个栈帧信息
                stackTrace[i] = getStackTraceElement(i);
        } else if (stackTrace == null) {
            return UNASSIGNED_STACK;
        }
        return stackTrace;
    }

public void setStackTrace(StackTraceElement[] stackTrace) 设置堆栈信息

    public void setStackTrace(StackTraceElement[] stackTrace) {
        // Validate argument
        //备份
        StackTraceElement[] defensiveCopy = stackTrace.clone();
        for (int i = 0; i < defensiveCopy.length; i++) {
            if (defensiveCopy[i] == null)
                throw new NullPointerException("stackTrace[" + i + "]");
        }

        synchronized (this) {
            if (this.stackTrace == null && // Immutable stack
                backtrace == null) // Test for out of protocol state
                return;
            this.stackTrace = defensiveCopy;
        }
    }

native int getStackTraceDepth(); 本地方法,得到栈帧深度

native StackTraceElement getStackTraceElement(int index); 本地方法,找到索引位置的栈帧信息

private void readObject(ObjectInputStream s) 私有方法,

    private void readObject(ObjectInputStream s)
        throws IOException, ClassNotFoundException {
        s.defaultReadObject();     // read in all fields
        if (suppressedExceptions != null) {
            List<Throwable> suppressed = null;
            if (suppressedExceptions.isEmpty()) {
                // Use the sentinel for a zero-length list
                suppressed = SUPPRESSED_SENTINEL;
            } else { // Copy Throwables to new list
                suppressed = new ArrayList<>(1);
                for (Throwable t : suppressedExceptions) {
                    // Enforce constraints on suppressed exceptions in
                    // case of corrupt or malicious stream.
                    if (t == null)
                        throw new NullPointerException(NULL_CAUSE_MESSAGE);
                    if (t == this)
                        throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE);
                    suppressed.add(t);
                }
            }
            suppressedExceptions = suppressed;
        }
        if (stackTrace != null) {
            if (stackTrace.length == 0) {
                stackTrace = UNASSIGNED_STACK.clone();
            }  else if (stackTrace.length == 1 &&
                        // Check for the marker of an immutable stack trace
                        SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(stackTrace[0])) {
                stackTrace = null;
            } else { // Verify stack trace elements are non-null.
                for(StackTraceElement ste : stackTrace) {
                    if (ste == null)
                        throw new NullPointerException("null StackTraceElement in serial stream. ");
                }
            }
        } else {
            // A null stackTrace field in the serial form can result
            // from an exception serialized without that field in
            // older JDK releases; treat such exceptions as having
            // empty stack traces.
            stackTrace = UNASSIGNED_STACK.clone();
        }
    }

private synchronized void writeObject(ObjectOutputStream s)

private synchronized void writeObject(ObjectOutputStream s)
        throws IOException {
        // Ensure that the stackTrace field is initialized to a
        // non-null value, if appropriate.  As of JDK 7, a null stack
        // trace field is a valid value indicating the stack trace
        // should not be set.
        getOurStackTrace();

        StackTraceElement[] oldStackTrace = stackTrace;
        try {
            if (stackTrace == null)
                stackTrace = SentinelHolder.STACK_TRACE_SENTINEL;
            s.defaultWriteObject();
        } finally {
            stackTrace = oldStackTrace;
        }
    }

public final synchronized void addSuppressed(Throwable exception) 添加被抑制的异常

    public final synchronized void addSuppressed(Throwable exception) {
    //如果要添加的异常是当前对象就抛出异常
        if (exception == this)
            throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE, exception);
//如果异常是空的抛出异常
        if (exception == null)
            throw new NullPointerException(NULL_CAUSE_MESSAGE);

        if (suppressedExceptions == null) // Suppressed exceptions not recorded
            return;

        if (suppressedExceptions == SUPPRESSED_SENTINEL)
            suppressedExceptions = new ArrayList<>(1);
//将异常加入list
        suppressedExceptions.add(exception);
    }

private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0]; 空的异常类数组

public final synchronized Throwable[] getSuppressed() 得到被抑制的异常

    public final synchronized Throwable[] getSuppressed() {
    //如果记录抑制异常的list是空的或者就是初始化状态那么就返回空数组
        if (suppressedExceptions == SUPPRESSED_SENTINEL ||
            suppressedExceptions == null)
            return EMPTY_THROWABLE_ARRAY;
        else
        //否则就把list加到空数组后,返回空数组
            return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值