Throwable

1. 使用大量数组和List常量: private static final StackTraceElement[] UNASSIGNED_STACK = new StackTraceElement[0];

2. 使用静态内部类

3. 拥有自身类的成员对象: cause, suppressedExceptions

public class Throwable implements Serializable {

    // Array & List常量
private static final StackTraceElement[] UNASSIGNED_STACK = new StackTraceElement[0];
private StackTraceElement[] stackTrace = UNASSIGNED_STACK; private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0]; private static final List<Throwable> SUPPRESSED_SENTINEL = Collections
.unmodifiableList(new ArrayList<Throwable>(0));
private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL; private Throwable cause = this; // 静态内部内
private static class SentinelHolder { public static final StackTraceElement STACK_TRACE_ELEMENT_SENTINEL = new StackTraceElement("", "", null, Integer.MIN_VALUE);
// 输出时当stackTrace为空时,即赋予该值
public static final StackTraceElement[] STACK_TRACE_SENTINEL = new StackTraceElement[] { STACK_TRACE_ELEMENT_SENTINEL };
} 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)
return; if (suppressedExceptions == SUPPRESSED_SENTINEL) // suppressedExceptions等于初始值,即创建list
suppressedExceptions = new ArrayList<>(1); suppressedExceptions.add(exception);
} public void printStackTrace(PrintWriter s) {
printStackTrace(new WrappedPrintWriter(s)); // 使用静态内部类
} private void printStackTrace(PrintStreamOrWriter s) {
Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());
dejaVu.add(this); synchronized (s.lock()) {
// Print our stack trace
s.println(this);
StackTraceElement[] trace = getOurStackTrace();
for (StackTraceElement traceElement : trace)
s.println("\tat " + traceElement); for (Throwable se : getSuppressed())
se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); Throwable ourCause = getCause();
if (ourCause != null)
ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
}
} private abstract static class PrintStreamOrWriter {
abstract Object lock(); abstract void println(Object o);
} private static class WrappedPrintStream extends PrintStreamOrWriter {
private final PrintStream printStream; WrappedPrintStream(PrintStream printStream) {
this.printStream = printStream;
} Object lock() {
return printStream;
} void println(Object o) {
printStream.println(o);
}
} private synchronized StackTraceElement[] getOurStackTrace() {
if (stackTrace == UNASSIGNED_STACK || (stackTrace == null && backtrace != null){
int depth = getStackTraceDepth();
stackTrace = new StackTraceElement[depth];
for (int i = 0; i < depth; i++)
stackTrace[i] = getStackTraceElement(i);
} else if (stackTrace == null) {
return UNASSIGNED_STACK;
}
return stackTrace;
} private void printEnclosedStackTrace(PrintStreamOrWriter s,
StackTraceElement[] enclosingTrace, String caption, String prefix, Set<Throwable> dejaVu) {
assert Thread.holdsLock(s.lock());
if (dejaVu.contains(this)) {
s.println("\t[CIRCULAR REFERENCE:" + this + "]");
} else {
dejaVu.add(this);
// Compute number of frames in common between this and enclosing
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--;
}
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 final synchronized Throwable[] getSuppressed() {
if (suppressedExceptions == SUPPRESSED_SENTINEL ||
suppressedExceptions == null)
return EMPTY_THROWABLE_ARRAY;
else
return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
} public synchronized Throwable getCause() {
return (cause==this ? null : cause);
} }

JDK Throwable的更多相关文章

  1. JDK动态代理

    一.基本概念 1.什么是代理? 在阐述JDK动态代理之前,我们很有必要先来弄明白代理的概念.代理这个词本身并不是计算机专用术语,它是生活中一个常用的概念.这里引用维基百科上的一句话对代理进行定义: A ...

  2. JDK动态代理实现原理

    之前虽然会用JDK的动态代理,但是有些问题却一直没有搞明白.比如说:InvocationHandler的invoke方法是由谁来调用的,代理对象是怎么生成的.直到看了他的文章才彻底明白,附网址:htt ...

  3. 静态代理和利用反射形成的动态代理(JDK动态代理)

    代理模式 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 静态代理 1.新建 ...

  4. 基于Spring AOP的JDK动态代理和CGLIB代理

    一.AOP的概念  在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的 ...

  5. Spring中的JDK动态代理

    Spring中的JDK动态代理 在JDK1.3以后提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.在Sun刚推出动态代理时,还很难想象它有多大的实际用途,现在动态代理是实现AOP的绝好底层 ...

  6. 模仿mybatis,用jdk proxy实现接口

    在mybatis中,我们都只需要定义一个mapper接口,但并不需要对它进行任务实现.只要有对就的mapper.xml文件就可以访问数据库.那么,没有接口的访问是如何实现的呢. 答案就是JDK pro ...

  7. AOP学习心得&jdk动态代理与cglib比较

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...

  8. springmvc 动态代理 JDK实现与模拟JDK纯手写实现。

    首先明白 动态代理和静态代理的区别: 静态代理:①持有被代理类的引用  ② 代理类一开始就被加载到内存中了(非常重要) 动态代理:JDK中的动态代理中的代理类是动态生成的.并且生成的动态代理类为$Pr ...

  9. Java 的静态代理 动态代理(JDK和cglib)

    转载:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是 ...

随机推荐

  1. android 中context的具体作用和意义

    context在android中是非常重要的一个类,此类一般用于activity之中 从字面意思来看,这是环境变量,内部实现了一些方法,但是此类也可以看做是一个句柄,用来唯一标示activity 举个 ...

  2. fragment界面交互实操(步骤)

    首先,新建一个继承了fragment类的类,在oncreateview方法中,使用方法的参数inflater,用其inflater.inflate(R.layout.fragment1,contain ...

  3. 百度Apollo解析——2.log系统

    Apollo中的glog 在Apollo中google glog 被广泛使用,glog 是 google 的一个 c++ 开源日志系统,轻巧灵活,入门简单,而且功能也比较完善. 1. 安装 以下是官方 ...

  4. Linux 设置新创建目录或文件的默认权限

    一.简介 在unix或者linux中,每创建一个文件或者目录时,这个文件或者目录都具有一个默认的权限,比如目录755,文件644,这些默认权限是通过"umask"权限掩码控制的.一 ...

  5. Luogu 4363 [九省联考2018]一双木棋chess

    发现数据范围很小,想到状压dp,然后就愣住不会了. 表示太菜了并没有接触过轮廓线dp这种操作. 首先发现合法的操作过程中一定是这样子的: 按照行来看发现每一行单调不递增. 我们用$1$来表示竖着的轮廓 ...

  6. NETTY4中的BYTEBUF 内存管理

    转 http://iteches.com/archives/65193 Netty4带来一个与众不同的特点是其ByteBuf的重现实现,老实说,java.nio.ByteBuf是我用得很不爽的一个AP ...

  7. 数据结构_calculator

    问题描述 小 V 发明了一个神奇的整数计算器:给定一个合法的表达式,这个计算器能求出这个表达式的最终答案.表达式可能包含:+:运算符,整数加法.如 1+1=2-:运算符,整数减法.如 1-1=0*:运 ...

  8. [转]MySQL时间与字符串相互转换

    转至:https://www.cnblogs.com/wangyongwen/p/6265126.html 时间.字符串.时间戳之间的互相转换很常用,但是几乎每次使用时候都喜欢去搜索一下用法:本文整理 ...

  9. Java50道经典习题-程序41 猴子分桃

    题目:海滩上有一堆桃子,五只猴子来分.第一只猴子把这堆桃子凭据分为五份,多了一个,这只猴子把多的一个扔入海中,拿走了一份.第二只猴子把剩下的桃子又平均分成五份,又多了一个,它同样把多的一个扔入海中,拿 ...

  10. HTTP 协议 -- 报头信息

    报头 每一个报头都是由 [名称 + ":" + 空格 + 值 + <CR><LF>] 组成.有四种不同类型的报头: 通用报头:可用于请求,也可以用于响应,它 ...