JAVA打印Hello World的底层实现

news2024/12/24 10:04:15

任何一个学过JAVA的人应该都对这段代码非常熟悉。空闲时间翻了下代码,看看它的底层是怎么实现的

public class HelloWorld {
    public static void main(String[] args) {
        System.out.print("Hello, World!");
    }
}

首先点开out,发现它是System类中的一个public static final变量,类型为PrintStream。为了找到它是怎么初始化的,一直往前翻到System类的构造函数

System类的注释中发现,VM会调用initPhase1这个方法来初始化这个类。先不管VM,先看下initPhase1方法做了什么

发现它用FileDescriptor.out创建了FileOutputStream对象,再用这个对象创建了PrintStream对象,最后调用native的setOut0

在创建PrintStream对象时,先将FileOutputStream封装成BufferedOutputStream,然后把BufferedOutputStream封装成OutputStreamWriter。这一步中会根据传入的字符集创建OutputStreamWriter中的编码器StreamEncoder

这样OutputStreamWriter就创建好了,在print的时候会调用这个类的方法,最后根据调用栈发现调用了FileOutputStream中的writeBytes方法

发现这个方法是native的,也就是说不在JAVA中实现,打开openjdk,checkout到tag jdk18

找到在jdk中的实现,发现调用了IO_AppendIO_Write,而这两个是宏定义,指向了handleWrite方法

在不同的平台下,这个方法有不同的实现

在windows下调用了WriteFile这个Win32 API

在linux下调用了unistd.h中定义的write方法

打开glibc,在write_nocancel.c下看到提供的write方法实现,通过一堆的宏定义最终是一个系统调用,调用了linux的write方法

在linux内核源代码中,找到write的SYSCALL,其中调用了ksys_write方法

这个方法中会获取fd,然后再通过vfs_write写入,顺着调用链一路找到了下面这个write方法

后面的两个参数很好理解,第一个tty_struct是什么?

In many computing contexts, “TTY” has become the name for any text terminal, such as an external console device, a user dialing into the system on a modem on a serial port device, a printing or graphical computer terminal on a computer’s serial port or the RS-232 port on a USB-to-RS-232 converter attached to a computer’s USB port, or even a terminal emulator application in the window system using a pseudoterminal device.

简单来说,就是一个文本终端。它也是一个虚拟文件系统,模拟了终端设备

回头看ksys_write方法的第一行,打开了一个文件描述符,其中调用了__fget_light方法

从第一行就能看到,从current中找到了files_structcurrent是一个宏定义,获取当前正在运行的任务current_task,而current_task->files是这个当前正在运行的任务所打开的文件信息

也就是说,进程打开了一个由虚拟文件系统管理的虚拟文件,它是一个伪终端PTY,然后向其中写入数据

在linux中输入tty,就可以看到对应的伪终端设备文件路径。往里写入数据,就可以实现向另一个终端中打印东西


参考:

  1. https://github.com/openjdk/jdk
  2. https://sourceware.org/git/glibc.git
  3. https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile
  4. https://www.linusakesson.net/programming/tty/index.php
  5. https://en.wikipedia.org/wiki/Devpts
  6. https://man7.org/linux/man-pages/man7/pty.7.html
  7. https://github.com/GNOME/vte

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/609410.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JAVA微服务_网关

服务网关 什么是服务网关/API网关 API Gateway(APIGW / API 网关),顾名思义,是系统对外的唯一入口。API网关封装了系统内部架构,为每个客户端提供定制的API。 近几年来移动应用与企业间互联需求的兴起。从以前单一的…

数据结构学习记录——图-最短路径问题(无权图单源最短路径算法、有权图单源最短路径算法、多源最短路径算法、Dijkstra(迪杰斯特拉)算法、Floyd算法)

目录 问题分类 无权图单源最短路径算法 思路 伪代码 时间复杂度 代码实现(C语言) 有权图单源最短路径算法 Dijkstra(迪杰斯特拉)算法 伪代码 时间复杂度 代码实现(C语言) 多源最短路径算法 …

《Apollo 智能驾驶进阶课程》四、感知

1. 感知概貌 2. 传感器和标定 激光雷达:主动式,发射功率限制 Camera: 被动式,受到光照影响大 Radar : 多普勒效率 相对速度 超声波: 感知距离有限,倒车时使用。 … 最后设备还在研发过程中。 PnP问题,解决标定。 IC…

chatgpt赋能python:Python实现字符串匹配的SEO优化

Python实现字符串匹配的SEO优化 在现代网络中,SEO(搜索引擎优化)已成为一项必不可少的技能。它涉及到网站的排名、用户的流量和营销策略等方面。关键字匹配是一种常见的SEO技术,它可以帮助你的网站在搜索引擎中排名更高。 本篇文…

Java 实现判定顺序表中是否包含某个元素的方法

一、思路 1.定义一个toFind变量来传入要查找的元素 2.遍历整个顺序表并判定当前下标的元素等不等于toFind 3.如果等于就返回一个true,否则返回false。 二、图解 首先调用以下的方法求出顺序表的长度,再使用 for 循环遍历每一个元素。 // 求顺序表的长…

《嵌入式系统》知识总结9:使用STM32固件库操纵GPIO

STM32固件库(函数库) “STM32 标准函数库”它是由 ST 公司针对 STM32 提供的函数接口,即 API (Application Program Interface),开发者可调用这些函数接口来配置 STM32的寄存器,使开发人员得以脱离最底层的寄存器操作&…

《阿里大数据之路》研读笔记(1)

首先先看到OLAP和OLTP的区别: OLTP(Online transaction processing):在线/联机事务处理。典型的OLTP类操作都比较简单,主要是对数据库中的数据进行增删改查,操作主体一般是产品的用户或者是操作人员。 OLAP(Online analytical processing):…

libVLC 抓取视频帧并渲染(QGraphicsView)

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 在《libVLC 抓取视频帧并渲染(QWidget)》介绍完 QWidget 对视频帧的渲染之后,是时候介绍第二种方式了 - QGraphicsView/QGraphicsScene/QGraphicsItem 图形视图框架。 基本步骤:自定义一个 QGraphicsIte…

RK3588平台开发系列讲解(驱动基础篇)等待队列

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、等待队列二、等待队列头三、等待队列项四、添加/删除队列五、等待唤醒六、等待事件沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 Linux 内核的等待队列是以双循环链表为基础数据结构,与进程调度机制紧…

KeepChatGPT: chatGPT增强插件,解决报错、保持活跃,让AI更丝滑

KeepChatGPT: chatGPT增强插件,解决报错、保持活跃,让AI更丝滑 这是一个ChatGPT的畅聊与增强插件。开源免费。不仅能解决所有报错不再刷新,还有保持活跃、取消审计、克隆对话、净化首页、展示大屏、展示全屏、言无不尽、拦截跟踪…

周赛348(模拟、反向思维、数位DP)

文章目录 [6462. 最小化字符串长度](https://leetcode.cn/problems/minimize-string-length/)阅读理解 [6424. 半有序排列](https://leetcode.cn/problems/semi-ordered-permutation/)模拟 [6472. 查询后矩阵的和](https://leetcode.cn/problems/sum-of-matrix-after-queries/)…

java并发编程:volatile关键字详解

文章目录 内存可见性禁止重排序什么是重排序?重排序的类型有哪些呢? 内存屏障volatile的用途 在Java中,volatile关键字有特殊的内存语义。volatile主要有以下两个功能: 保证变量的内存可见性禁止volatile变量与普通变量重排序 内存可见性 …

RK3588平台开发系列讲解(驱动基础篇)中断下文之 tasklet

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、中断下文之 tasklet二、tasklet相关函数介绍三、tasklet使用示例四、中断视频介绍沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 介绍中断下文之 tasklet 的基础理论知识。 一、中断下文之 tasklet 中断…

C C++ 的内存管理(C++)

目录 C / C 的内存分布 C / C 程序内存区域划分:​ C语言内存管理 C中动态内存管理方式: C内存管理 C内存管理的方式: new / delete 操作内置类型 new 和 delete 操作自定义类型 new 和 delete 与 malloc 和 free 的区别: operato…

基于Springboot的漫画之家系统设计实现

💞文末获取源码联系🙉 👇🏻 精选专栏推荐收藏订阅👇🏻 🎀Java项目精选实战案例《600套》😘 https://blog.csdn.net/rucoding/category_12319634.html 文章目录 1、演示视频2、课题背…

QSS盒子模型入门指南:了解和应用基础知识

目录 1. QSS盒子模型的组成部分2. QSS盒子模型的属性3. QSS盒子模型的布局4. QSS盒子模型的调试工具结论 #概述 QSS(Qt Style Sheets)是一种用于美化和定制化Qt应用程序的样式表语言。了解和掌握QSS盒子模型的基本概念对于创建漂亮的用户界面布局至关重要…

javascript基础二十七:说说 JavaScript 数字精度丢失的问题,解决方案?

一、场景复现 一个经典的面试题 0.1 0.2 0.3 // false 为什么是false呢? 先看下面这个比喻 比如一个数 130.33333333… 这是一个除不尽的运算,3会一直无限循环,数学可以表示,但是计算机要存储,方便下次再使用,但…

IMX6ULL裸机篇之I2C实验-硬件原理图

一. I2C 实验简介 I2C实验,我们就来学习如何使用 I.MX6U 的 I2C 接口来驱动 AP3216C,读取 AP3216C 的传感器数据。 AP3216C是一个三合一的环境光传感器,ALSPSIRLED,ALS是环境光,PS是接近传感器,IR是红外L…

2023 华为 Datacom-HCIE 真题题库 12/12(完结)--含解析

单项选择题 1.[试题编号:190728] (单选题)以下哪种工具不能用来匹配BGP路由条目? A、基本ACL B、高级ACL C、IP PREFIX LIST D、Community Filter 答案:B 解析:高级ACL是一种用于过滤IPv4报文的ACL&#…

多层级table联动

elementui 多层级table联动: 引用: https://blog.csdn.net/weixin_44780971/article/details/130054925 https://blog.csdn.net/qq_42581563/article/details/114325920 需要了解的属性: select-all 全选的时候执行select : 选择…