System.out.print实现原理猜解
我们往往在main中直接调用System.out.print方法来打印,但是其实就这简单的一步里面有很多的玄机,因为main是static的,所以只能调用static的函数,那么print是static的吗?我一直有这个疑问,今天专门查阅了下源码,说下我的理解:(源码只贴出来部分对理解有用的)
源码里面:public final class System 直接在lang包里面。所以可以直接不通过包名就直接调用system类。里面还有:
public final static PrintStream out = nullPrintStream();
............
............
private static PrintStream nullPrintStream() throws NullPointerException {
if (currentTimeMillis() > 0) {
return null;
}
throw new NullPointerException();
}
可以看出out是system的静态成员,所以可以通过system.out直接访问到,但是这时候又有问题了,因为 nullPrintStream()这个函数返回值是null的,怎么可以调用printstream的方法呢。看out的注释:
/**
* The following two methods exist because in, out, and err must be
* initialized to null. The compiler, however, cannot be permitted to
* inline access to them, since they are later set to more sensible values
* by initializeSystemClass().
*/
大概翻译后知道刚开始的时候确实是都是null的,那么什么时候能把out指向标准输出的呢?注释说看initializeSystemClass()这个函数。
/**
* Initialize the system class. Called after thread initialization.
*/
private static void initializeSystemClass() {
props = new Properties();
initProperties(props);
sun.misc.Version.init();
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
.................
setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));
...............
...............
接着找到FileDescriptor这个类中的静态成员 out:(用自身定义自身)
public static final FileDescriptor out = standardStream(1);
以及standardStream()方法:
private static FileDescriptor standardStream(int fd) {
FileDescriptor desc = new FileDescriptor();
desc.handle = set(fd);
return desc;
}
这时候返回了 handle为1的FileDescriptor; 在传统的unix的系统中,文件描述符为0,1,2分别表示为标准输入,标准输出和错误输出。
最后调用了setout0方法:
private static native void setOut0(PrintStream out);
到这里,setout0是native方法,所以再也追踪不到以后的细节了,而到这时候,out的出路似乎还没有找到。但是。在system类中有setout方法即:
public static void setOut(PrintStream out) {
checkIO();
setOut0(out);
}
调用了setout0()方法,而我们知道setout方法是重置输出流的对象的,因此虽然我们看不到setout0的细节,但是因为setout调用了setout0,我们可以大致猜到setout0是通过调用底层的代码实现对out的流的重定位的,而initializeSystemClass()这个函数也调用了setout0将fd为1的文件封装成文件流,再封装成缓冲流,再封装成打印流,最后通过setout0将out与这个流绑定。这样一切就都说通了。
原文链接:http://www.cnblogs.com/zr-714/archive/2012/03/22/2411926.html
System.out.print实现原理猜解相关推荐
- JVM源码分析之System.currentTimeMillis及nanoTime原理详解
概述 上周@望陶问了我一个现象很诡异的问题,说JDK7和JDK8下的System.nanoTime()输出完全不一样,而且差距还非常大,是不是两个版本里的实现不一样,之前我也没注意过这个细节,觉得非常 ...
- nanotime java 博客园_JVM源码分析之System.currentTimeMillis及nanoTime原理详解
JDK7和JDK8下的System.nanoTime()输出完全不一样,而且差距还非常大,是不是两个版本里的实现不一样,之前我也没注意过这个细节,觉得非常奇怪,于是自己也在本地mac机器上马上测试了一 ...
- python sql注入脚本_python辅助sql手工注入猜解数据库案例分析
发现存在sql注入漏洞 简单一点可以直接用sqlmap工具暴库 但是如果想深入理解sql注入的原理,可以尝试手工注入,配合python脚本实现手工猜解数据库 首先hachbar开启 获取cms登录后的 ...
- mysql路径猜解_猜解数据库(MYSQL)信息
1 importrequests2 3 ################################################################# 4 #http://43.2 ...
- Java ArrayList的实现原理详解
ArrayList是Java List类型的集合类中最常使用的,本文基于Java1.8,对于ArrayList的实现原理做一下详细讲解. (Java1.8源码:http://docs.oracle.c ...
- Java集合迭代器原理图解_Java Iterator接口遍历单列集合迭代器原理详解
这篇文章主要介绍了Java Iterator接口遍历单列集合迭代器原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Iterator接口概述 ...
- EMD算法之Hilbert-Huang Transform原理详解和案例分析
目录 Hilbert-Huang Transform 希尔伯特-黄变换 Section I 人物简介 Section II Hilbert-Huang的应用领域 Section III Hilbert ...
- 图像质量损失函数SSIM Loss的原理详解和代码具体实现
本文转自微信公众号SIGAI 文章PDF见: http://www.tensorinfinity.com/paper_164.html http://www.360doc.com/content/19 ...
- 操作系统:基于页面置换算法的缓存原理详解(下)
概述: 在上一篇<操作系统:基于页面置换算法的缓存原理详解(上)>中,我们主要阐述了FIFO.LRU和Clock页面置换算法.接着上一篇说到的,本文也有三个核心算法要讲解.分别是LFU(L ...
最新文章
- go3--常量和类型转换
- jupyter笔记本_如何为Jupyter笔记本电脑设置PySpark
- asp.net MVC2 Jquery
- Redis常用五大数据类型
- Odoo中最小库存规则和按订单生成规则的区别
- 爱立信:用什么保持全球老大的地位?
- CentOS 6.3下rsync服务器的安装与配置[转]
- 少年班招生大扩容,清华、北大加入争夺行列,每年增至近800人
- [Android]对MVC和MVP的总结
- C/C++ 工具函数 —— 大端模式和小端模式的互换
- 仿分词统计的MapReduce 程序。
- 运维半夜给我打电话,弹幕服务产生大量异常日志,没办法起床排bug...
- Apache SSI 远程命令执行漏洞
- 与911S5类似的MaxProxy代理怎么样?
- 关于搞国外广告联盟的一些思路
- 运用卡方检验(独立性检验)来分析问卷的两个问题之间的关联性
- 三国志战略版:Daniel_张角分析
- 往哪里看低买高卖和利润之间
- PAR 相控阵方法,阵元间隔原理
- gta5结局杀老崔我哭了_GTA5:大结局最艰难的抉择!杀掉老崔还是麦克?
热门文章
- 解决“The executable was signed with invalid entitlements.”问题
- [转载] 深入理解Linux修改hostname
- TinyFrame开篇:基于CodeFirst的ORM
- Android之使用AlertDialog类和AlertDialog.Builder类创建带取消,确定,中立的对话框
- logback利用mdc机制为日志增加traceId
- c++语言中for循环语句,C++ 循环
- Vue自定义组件——非单文件组件
- ❤️万字总结八大排序:冒泡排序,选择排序,插入排序,堆排序,希尔排序,归并排序,计数排序❤️
- html5 标准结构_IT兄弟连 HTML5教程 HTML文件的主体结构
- python操作redis set_Python操作redis学习系列之(集合)set,redis set详解 (六)