转载请注明源出处:http://www.cnblogs.com/lighten/p/6992043.html
在讲解Java的文件流之前,先来认识一下Java的文件系统的实现。值得一提的是,Java8与Java7相比,对这一块做了一些改动,接下来会进行对比介绍,但主要还是以Java8为主。
首先,Java8多了一个DefaultFileSystem,但少了一个Win32FileSystem类,其次两者的抽象父类FileSystem有些许区别。Java7的抽象父类有一个静态native方法,FileSystem getFileSystem();
而Java8没有。在File类文件我们可以看到,Java7获取电脑主机的文件系统就是通过FileSystem.getFileSystem();而Java8则是通过DefaultFileSystem.getFileSystem();
这个WinNTFileSystem是两个版本都有的一个类,但实现不一样,由于Java7存在Win32FileSystem,其WinNTFileSystem类是继承自Win32FileSystem,Java8没有这个类,所以其是直接继承抽象父类FileSystem。从这里我们也可以看出区别了,Java7是通过native方法来选择主机的文件系统实现类实例。但是Java8只有WinNTFileSystem一个实现类,没有Win32FileSystem的,因此就是直接返回一个WinNTFileSystem实例。后面将比较WinNTFileSystem在两个版本的不同之处。
FileSystem中定义了许多的抽象方法,具体如下:
涉及到文件系统的查询,添加删除都是native方法,具体如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private
native
String getDriveDirectory(
`int
drive);
//获取磁盘目录,A~Z盘符`
private
native
String canonicalize0(String path)
throws
IOException;
// 规范化文件路径
private
native
String canonicalizeWithPrefix0(String canonicalPrefix,
String pathWithCanonicalPrefix)
throws
IOException;
// 这个也是规范化,不过其假定之前的路径都是规范的,只需要规范路径最后一个元素
// 一些文件的操作,文件信息的读取,删除创建目录及文件权限等等
public
native
int
getBooleanAttributes(File f);
public
native
boolean
checkAccess(File f,
int
access);
public
native
long
getLastModifiedTime(File f);
public
native
long
getLength(File f);
public
native
boolean
setPermission(File f,
int
access,
boolean
enable,
boolean
owneronly);
public
native
boolean
createFileExclusively(String path)
throws
IOException;
public
native
String[] list(File f);
public
native
boolean
createDirectory(File f);
public
native
boolean
setLastModifiedTime(File f,
long
time);
public
native
boolean
setReadOnly(File f);
private
native
boolean
delete0(File f);
private
native
boolean
rename0(File f1, File f2);
private
static
native
int
listRoots0();
private
native
long
getSpace0(File f,
int
t);
private
static
native
void
initIDs();
Java7与Java8针对于文件的一些操作方法,在WinNTFileSystem大致相同,不过Java7是将其实现在Win32FileSystem类中。虽说是大致相同,但是还是有些许差别。Win32FileSystem获取磁盘使用大小如下:
两个版本的WinNTFileSystem的实现却是一样的。
这里为什么不需要兼容Win32就不清楚了,或许是在使用时判断过了,或许是native方法getSpace0的实现方法不同了。而除了这个方法,两者的这个WinNTFileSystem都实现都是一样的,Java7的Win32FileSystem就是一个getSpace与WinNTFileSystem,这也难怪移除了这个类,只使用WinNTFileSystem这个类了。
由于大部分方法都是些native方法,调用这些方法的方法实现也比较简单,这里就不进行说明了,直接看源码就很明白了。这里简单介绍一下文件路径的处理过程。
1.public String canonicalize(String path);
(1)判断path长度:
长度为两位,格式是字母:,则返回大写字母:,比如C:
长度为三位,格式是字母:\,则返回大写字母:\,如C:\\
(2)判断设置是否需要缓存路径:
不需要,调用native方法canonicalize0
需要,获取缓存cache,存在就直接返回。不存在:
(a)如果使用缓存的路径前缀,通过parentOrNull获取文件的父路径,没有则为null。如果父路径不为空,取缓存prefixCache,缓存为空,就调用canonicalizeWithPrefix,注意这里放入的缓存是cache,这个结果就是我们需要的整个路径格式化结果。
(b)如果结果还是null,就使用navtive方法的canonicalize0获取格式化路径。放入cache缓存。注意,如果需要缓存前缀,并且a步骤解析的父路径不为空,就重新通过格式化后的路径获取父文件,存在且格式化后的路径也是一个文件存在且不是目录,就将结果存入prefixCache。
这个解析过程看过去很麻烦,为什么不直接调用canonicalize0方法。主要是通过使用缓存,可以改进启动的性能。值得注意的是,a步骤和b步骤放入cache中的键值写法是不一样的,但是结果是一致的,cache处理的是相同path的格式化路径,键值就是传入的path,prefixCache处理的是父目录目录的格式化路径,取出来的是父目录的格式化路径,确保与native算法canonicalize_md.c中的结果一致,进行了相应的转换处理,所以源码看过去有些繁琐。
File类有四种构造方法:
不管是哪种方式,最终都是要初始化两个参数:
下面这些文件方式,都是使用了FileSystem的与路径处理相关的方法:
而剩下的所有方法,都与FileSystem的native方法相关了,没有太多介绍的必要。唯一有点意思的就是deleteOnExit()方法,其实现与DeleteOnExitHook类相关,这个类最后会介绍。
第2节讲到过获取路径的标准字符串时使用到了缓存,这个缓存就是ExpiringCache类,这是一个带时效的缓存,实现关键就在于初始化的时候需要给一个超时时间
其保存的不只是键值,值是一个Entry,有额外的保存时间字段
在保存的时候会加上保存时间戳,获取的时候会比较一下当前时间是否超时。超时就清除返回null,否则就返回所需要的值。
File类的deleteOnExit()方法就是使用了这个类。实际上开源框架dubbo的停机也使用了其中的机制。Java目前在JVM关闭的时候提供了一个钩子(hook),这个允许你在JVM关闭的时候执行一些代码,这个类就是在关闭的时候执行删除需要删除的文件。一般是通过Runtime.getRuntime().addShutdownHook(new Thread())进行的。DeleteOnExitHook是使用了一个sun.misc.SharedSecrets类来完成的,原理应该一样的。hook在以下情况会生效:
1.程序运行完成退出
2.使用System.exit()方法退出
3.终端运行时使用ctrl+c中止程序
4.系统关闭
5.OutOfMemory造成宕机
6.kill pid命令杀死进程(kill -9 pid不行)
原网址: 访问
创建于: 2023-07-11 09:51:54
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
java windows火焰图_mob64ca12ec8020的技术博客_51CTO博客 - 在windows下不可行,不知道作者是怎样搞的 监听SpringBoot 服务启动成功事件并打印信息_监听springboot启动完毕-CSDN博客 SpringBoot中就绪探针和存活探针_management.endpoint.health.probes.enabled-CSDN博客 u2u转换板 - 嘉立创EDA开源硬件平台 Spring Boot 项目的轻量级 HTTP 客户端 retrofit 框架,快来试试它!_Java精选-CSDN博客 手把手教你打造一套最牛的知识笔记管理系统! - 知乎 - 想法有重合-理论可参考 安宇雨 闲鱼 机械键盘 客制化 开贴记录 文本 linux 使用find命令查找包含某字符串的文件_beijihukk的博客-CSDN博客_find 查找字符串 ---- mac 也适用 安宇雨 打字音 记录集合 B站 bilibili 自行搭建 开坑 真正的客制化 安宇雨 黑苹果开坑 查找工具包maven pom 引用地 工具网站 Dantelis 介绍的玩轴入坑攻略 --- 关于轴的一些说法 --- 非官方 ---- 心得而已 --- 长期开坑更新 [本人问题][新开坑位]关于自动化测试的工具与平台应用 机械键盘 开团 网站记录 -- 能做一个收集的程序就好了 不过现在没时间 -- 信息大多是在群里发的 - 你要让垃圾佬 都去一个地方看难度也是很大的 精神支柱 [超级前台]sprinbboot maven superdesk-app 记录 [信息有用] [环境准备] [基本完成] [sebp/elk] 给已创建的Docker容器增加新的端口映射 - qq_30599553的博客 - CSDN博客 [正在研究] Elasticsearch, Logstash, Kibana (ELK) Docker image documentation elasticsearch centos 安装记录 及 启动手记 正式服务器 39 elasticsearch 问题合集 不断更新 6.1.1 | 6.5.1 两个版本 博客程序 - 测试 - bug记录 等等问题 laravel的启动过程解析 - lpfuture - 博客园 OAuth2 Server PHP 用 Laravel 搭建带 OAuth2 验证的 RESTful 服务 | Laravel China 社区 - 高品质的 Laravel 和 PHP 开发者社区 利用Laravel 搭建oauth2 API接口 附 Unauthenticated 解决办法 - 煮茶的博客 - SegmentFault 思否 使用 OAuth2-Server-php 搭建 OAuth2 Server - 午时的海 - 博客园 基于PHP构建OAuth 2.0 服务端 认证平台 - Endv - 博客园 Laravel 的 Artisan 命令行工具 Laravel 的文件系统和云存储功能集成 浅谈Chromium中的设计模式--终--Observer模式 浅谈Chromium中的设计模式--二--pre/post和Delegate模式 浅谈Chromium中的设计模式--一--Chromium中模块分层和进程模型 DeepMind 4 Hacking Yourself README.md update 20211011
Laravel China 简书 知乎 博客园 CSDN博客 开源中国 Go Further Ryan是菜鸟 | LNMP技术栈笔记 云栖社区-阿里云 Netflix技术博客 Techie Delight Linkedin技术博客 Dropbox技术博客 Facebook技术博客 淘宝中间件团队 美团技术博客 360技术博客 古巷博客 - 一个专注于分享的不正常博客 软件测试知识传播 - 测试窝 有赞技术团队 阮一峰 语雀 静觅丨崔庆才的个人博客 软件测试从业者综合能力提升 - isTester IBM Java 开发 使用开放 Java 生态系统开发现代应用程序 pengdai 一个强大的博主 HTML5资源教程 | 分享HTML5开发资源和开发教程 蘑菇博客 - 专注于技术分享的博客平台 个人博客-leapMie 流星007 CSDN博客 - 舍其小伙伴 稀土掘金 Go 技术论坛 | Golang / Go 语言中国知识社区
最新评论