e.printStackTrace() 原理的分析
e.printStackTrace();
先查看下源码

如图片中1所示,使用的是 PrintStreamOrWriter
public void printStackTrace() {
printStackTrace(System.err);
}
/**
* Prints this throwable and its backtrace to the specified print stream.
*
* @param s {@code PrintStream} to use for output
*/
public void printStackTrace(PrintStream s) {
printStackTrace(new WrappedPrintStream(s));
}
private void printStackTrace(PrintStreamOrWriter s) {
// Guard against malicious overrides of Throwable.equals by
// using a Set with identity equality semantics.
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);
// 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);
}
}
,而这来源于 PrintStream,而 PrintStream 又继承 FilterOutputStream ,是文件输出流,会肯定会影响内存的变动
ublic class PrintStream extends FilterOutputStream
implements Appendable, Closeable
{ private final boolean autoFlush;
private boolean trouble = false;
private Formatter formatter; /**
* Track both the text- and character-output streams, so that their buffers
* can be flushed without flushing the entire stream.
*/
private BufferedWriter textOut;
private OutputStreamWriter charOut; /**
* requireNonNull is explicitly declared here so as not to create an extra
* dependency on java.util.Objects.requireNonNull. PrintStream is loaded
* early during system initialization.
*/
private static <T> T requireNonNull(T obj, String message) {
if (obj == null)
throw new NullPointerException(message);
return obj;
}
}
而图片中二所示的lock锁,锁住这个流对象,就是占用住了内存不让进行gc回收,先输出打印,
跟踪s.println(this) 也就是PrintStream的方法,发现是会使用bufferedwriter和outputstream
/**
* Prints an Object and then terminate the line. This method calls
* at first String.valueOf(x) to get the printed object's string value,
* then behaves as
* though it invokes <code>{@link #print(String)}</code> and then
* <code>{@link #println()}</code>.
*
* @param x The <code>Object</code> to be printed.
*/
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
/**
* Prints a string. If the argument is <code>null</code> then the string
* <code>"null"</code> is printed. Otherwise, the string's characters are
* converted into bytes according to the platform's default character
* encoding, and these bytes are written in exactly the manner of the
* <code>{@link #write(int)}</code> method.
*
* @param s The <code>String</code> to be printed
*/
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
private void write(String s) {
try {
synchronized (this) {
ensureOpen();
textOut.write(s);
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush && (s.indexOf('\n') >= 0))
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
后又获取 StackTraceElement ,也就是获取方法调用者的具体信息 的。 循环打印
然后又获取Throwable报错的堆栈跟踪异常数据 的数组, 循环打印。
特意说下,在 printEnclosedStackTrace的方法中使用
assert Thread.holdsLock(s.lock());
这个是断言,判断当前线程是是否获得当前流的锁,判断是否成功。
专业一点的词叫:为了确保该代码所在的线程正持有所在类的对象作为锁。
意思执行的过程中,这个流对象只能被当前流锁占用不能被切换到其它线程。如果报错多的话,那么这些线程都会在统计这些报错信息,而不能去执行其它东西了
来源
java中e.printStackTrace()不要使用,请使用logger记录
Thread.holdsLock(Object)方法、assert断言、宏
e.printStackTrace() 原理的分析的更多相关文章
- 20169212《Linux内核原理与分析》课程总结
20169212<Linux内核原理与分析>课程总结 每周作业链接汇总 第一周作业:完成linux基础入门实验,了解一些基础的命令操作. 第二周作业:学习MOOC课程--计算机是如何工作的 ...
- 20169212《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...
- AJAX练习(一):制作可以自动校验的表单(从原理上分析ajax的作用)
继上文(AJAX(一)AJAX的简介和基础)作为联系. 传统网页在注册时检测用户名是否被占用,传统的校验显然缓慢笨拙. 当ajax出现后,这种体验有了很大的改观,因为在用户填写表单时,签名的表单项已经 ...
- 20169210《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...
- wp7之换肤原理简单分析
wp7之换肤原理简单分析 纠结很久...感觉勉强过得去啦.还望各位大牛指点江山 百度找到这篇参考文章http://www.cnblogs.com/sonyye/archive/2012/03/12/2 ...
- 2018-2019-1 20189221 《Linux内核原理与分析》第九周作业
2018-2019-1 20189221 <Linux内核原理与分析>第九周作业 实验八 理理解进程调度时机跟踪分析进程调度与进程切换的过程 进程调度 进度调度时机: 1.中断处理过程(包 ...
- 2018-2019-1 20189221 《Linux内核原理与分析》第八周作业
2018-2019-1 20189221 <Linux内核原理与分析>第八周作业 实验七 编译链接过程 gcc –e –o hello.cpp hello.c / gcc -x cpp-o ...
- 2018-2019-1 20189221 《Linux内核原理与分析》第七周作业
2018-2019-1 20189221 <Linux内核原理与分析>第七周作业 实验六 分析Linux内核创建一个新进程的过程 代码分析 task_struct: struct task ...
- 2018-2019-1 20189221 《Linux内核原理与分析》第六周作业
2018-2019-1 20189221 <Linux内核原理与分析>第六周作业 实验五 实验过程 将Fork函数移植到Linux的MenuOS fork()函数通过系统调用创建一个与原来 ...
随机推荐
- Bugku CTF练习题---杂项---隐写3
Bugku CTF练习题---杂项---隐写3 flag:flag{He1l0_d4_ba1} 解题步骤: 1.观察题目,下载附件 2.打开图片,发现是一张大白,仔细观察一下总感觉少了点东西,这张图好 ...
- 继承 & super & 方法覆盖
简单继承 细节1: 细节2: 子类创建对象,先 父类构造器,后 子类的构造器,因为(默认的super) 细节3: 假设父类只有一个有参构造器, 此时需要子类用上super给定父类参数,才能通过编译 ...
- python3 获取函数变量
Python 3.8可以使用f字符串调试功能: 1 test_dict = {1: "1", 2: "2", 3: "3"} 2 print ...
- LeetCode数组刷题——448、48、240、769
1.[LeetCode448]:448. 找到所有数组中消失的数字 题目分析: 1-n之间有重复的,有没出现的,有出现一次.使用hashmap,空间复杂度为O(n) 方法一:哈希表,但是空间复杂度超过 ...
- 卧槽!华为《Linux中文手册》火了,完整版 PDF 开放下载!
这是华为工程师基于最新的Linux编写,循序渐进地对Linux进行讲解.对于零基础可以作为Linux的快速入门教材.我希望能为大家提供切实的帮助. 资料介绍 涵盖基础.系统管理.应用.开发.服务器配置 ...
- Oracle 19c单实例部署
目录 Oracle 19c单实例部署: 1.配置yum: 2.安装rpm包: 3.设置hostname: 4.配置hostname解析: 5.配置时钟同步服务(ntp): 6.检查及配置内核参数: 7 ...
- 2022年5月11日,NBMiner发布了41.3版本,在内核中加入了100%LHR解锁器,从此NVIDIA的显卡再无锁卡一说
2022年5月11日,NBMiner发布NBMiner_41.3版本,主要提升了稳定性. 2022年5月8日,NBMiner发布NBMiner_41.0版本,在最新的内核 ...
- 请求扩展、蓝图、g对象
今日内容概要 请求扩展 蓝图 g对象 内容详细 1.请求扩展 # 在请求来了,请求走了,可以做一些校验和拦截,通过装饰器来实现 7 个 # 1 before_request 类比django中间件中的 ...
- 有了这10个GitHub仓库,开发者如同buff加持
摘要:列出了10个极好的仓库,它们为所有web和软件开发人员提供了巨大的价值. 本文分享自华为云社区<所有开发者都应该知道的10个GitHub仓库>,作者: Ocean2022 . 除了作 ...
- 好客租房5-React脚手架的应用
3.1react脚手架意义 1脚手架是开发现代web应用的必备 2充分利用webpack babel eslint等工具进行使用 3零配置 4关注业务即可 3.2使用react脚手架初始化项目 1初始 ...