1. 概述

今天在项目中看到下面两行代码,看注释说是获取当前工作路径,之前也没有用过这种用法,比较好奇还能这样用,所以研究了一下源码。

//获取当前工作路径
File file = new File("");
String currentWorkDirectory = file.getAbsolutePath();

2. new File("")解析

首先,new File()是创建一个虚拟的文件(File)对象,通过这个对象可以调用很多方法来获取文件和目录的相关信息。以下列出一些常用方法:

2.1 File的常用方法

方法签名 作用
boolean delete() 删除文件或目录
void deleteOnExit() 在jvm退出时删除文件或目录
boolean createNewFile() 当以这个文件名命名的文件不存在时,创建一个新的空文件
boolean exists() 判断文件或目录是否存在
String getAbsolutePath() 获取File对象的绝对路径
String getName() 获取文件或目录名称
File getParentFile() 获取父File对象
String getPath() 获取File对象创建时传入的pathname参数
boolean isDirectory() 判断是否是目录
File[] listFiles() 列出当前目录下的所有文件
boolean mkdir() 创建单个目录
boolean mkdirs() 创建多级目录

2.2 new File("")做了什么

我们先来看看源码是怎么描述的:



其中注释的意思是:将指定的文件路径转换为一个绝对路径,然后创建一个新的File实例。如果给定的文件路径参数为空值,则返回空的绝对路径名。

官方的注释比较难理解,通俗的将就是,当我传入一个相对路径就会转换为绝对路径,当我传入一个""参数时,就只有一个绝对路径。那么这个绝对路径代表什么含义呢?

2.3 深入源码看File绝对路径(abstract pathname)的含义

其实我们可以看到new File(String pathname)这个构造方法只设置了相对路径和解析相对路径的长度。并没有有关绝对路径的操作。那么究竟是在哪里设置的绝对路径呢?这个就涉及到getAbsolutePath()方法了。

下面我们看一下getAbsolutePath()方法做了什么:



从注释可以看出,如果在new File()的时候传入的pathname已经是绝对路径的话,那么这个方法的返回就和getPath()一样,如果传入的是空字符串的话,那么就返回当前目录的路径,通过系统属性user.dir获取。

那么我们继续往下看:

点进去resolve()方法可以看到返回值实际是从getUserPath()这个方法获取的。

getUserPath()方法调用了System.getProperty("user.dir")方法来获取user.dir这个key的配置。再往里面看user.dir的值其实是从props这个Properties对象中获取的。

那props又是从哪里拿到这个值的呢?我们接着往下看:

在System类里面对着props这个属性用ctrl+鼠标左键查找props在哪几个地方使用了。可以看到有一个setProperties(Properties props)方法。再对着setProperties这个方法使用ctrl+鼠标左键查找。

在com.sun.org.apache.xalan.internal.xslt.Process的main方法里面我们可以看到,执行了System.setProperties(props),而System.setProperties(props)调用了本地方法private static native Properties initProperties(Properties props)对props进行初始化。

到这里的话,其实java源代码已经结束了,总结来说就是jvm在启动的时候调用了System类的private static native Properties initProperties(Properties props)本地方法对props属性进行初始化,设置了user.dir的值。

这时可能还有些好奇宝宝不甘心,为什么调用了这个本地方法就可以获取user.dir的值,那么我们就来研究一下openjdk的c语言源码吧。

2.4 深入openjdk源码

我们从github上搜索到openjdk的源码仓库,随便找一个java8的tag来研究initProperties()这个本地方法到底做了什么。

github的openjdk代码仓库

  1. 首先我们找到jdk/src/share/native/java/lang目录下面的System.c文件。在里面搜索一下initProperties,可以看到有一个Java_java_lang_System_initProperties方法。

  2. 接着我们在这个方法里面搜索user_dir,可以看到值是从一个sprops指针中获取的,而sprops从上一张图可以看出是从GetJavaProperties(env)这个方法获取的值。

  3. 那我们ctrl+shift+F全局搜索一下GetJavaProperties这个方法。可以看到jdk/src/windows/native/java/lang/java_props_md.c文件中有这个方法,从文件路径可以看出这个文件是windows系统下执行的。

  4. 接着在这个方法里面搜索user_dir,可以看到user_dir实际是从GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR), buf)方法里面获取值的。GetCurrentDirectoryW这个方法就是windows的系统函数,用来获取当前工作目录。

到这里jdk源码解析就结束了,可以看到在windows系统下是调用了它的系统函数获取当前工作目录。

备注:_wcsdup(buf)方法是c语言的库函数,作用是分配一块新的空间,然后从buf数组里面获取值赋值给新创建的空间。

3. 总结

  1. 绝对路径是什么:当前工作目录,就是当前项目的根路径
  2. 使用new File("")创建File对象时,绝对路径其实是getAbsolutePath()方法获取的,new File("")只是设置了path=""
  3. System.props这个属性其实包含了很多值,如:java.version、user.home等等,可以看源码中的注释
  4. 通过System.getProperty(key)可以获取系统的一些配置信息

从new File("")到jdk源码的更多相关文章

  1. eclipse调试jdk源码

    摘要 介绍使用eclipse调试jdk源码 java是一门开源的程序设计语言,喜欢研究源码的java开发者总会忍不住debug一下jdk源码.虽然官方的jdk自带了源码包src.zip,然而在debu ...

  2. jdk源码调试功能

    JDK源码重新编译——支持eclipse调试JDK源码--转载 最近在研究jdk源码,发现debug时无法查看源码里的变量值. 因为sun提供的jdk并不能查看运行中的局部变量,需要重新编译一下rt. ...

  3. JDK源码重新编译——支持eclipse调试JDK源码--转载

    最近在研究jdk源码,发现debug时无法查看源码里的变量值. 因为sun提供的jdk并不能查看运行中的局部变量,需要重新编译一下rt.jar. 下面这六步是编译jdk的具体步骤: Step 1:   ...

  4. Eclipse用法和技巧二十三:查看JDK源码

    使用java开发,如果能阅读JDK的经典代码,对自己的水平提高是很有帮助的.笔者在实际工作中总结了两种阅读JDK源码的方式.第一种下载android源代码,直接在android源码代码中,这里的代码虽 ...

  5. eclipse如何debug调试jdk源码(任何源码)并显示局部变量

    最近要看struts2源码 仿照了一下查看jdk源码的方式 首先你要有strtus2的jar包和源码,在struts官网上下载时,选择full版本,里面会有src也就是源码了. jar导入项目,保证可 ...

  6. 跟踪调试JDK源码时遇到的问题及解决方法

    目录 问题描述 解决思路 在IntelliJ IDEA中调试JDK源码 在eclipse中调试JDK源码 总结 问题描述 最近在研究MyBatis的缓存机制,需要回顾一下HashMap的实现原理.于是 ...

  7. 随手用python写一个下载jdk源码爬虫

    最近在研读jdk源码,网上找了下资源,发现都不完整. 后来新发现了一个有完整源码的地方,主要包括了java,c,c++的东西,装逼需要,就想拿来玩玩.但是,找了好多种下载打开的方式,发现都不对.于是, ...

  8. 2018-08-27 使用JDT核心库解析JDK源码后初步分析API命名

    源自术语词典API项目 · Issue #85 · program-in-chinese/overview, 打算先用早先的代码提取JDK API中的类/方法/参数名, 看看有哪些词需要翻译. 源码在 ...

  9. JDK源码阅读顺序

      很多java开发的小伙伴都会阅读jdk源码,然而确不知道应该从哪读起.以下为小编整理的通常所需阅读的源码范围. 标题为包名,后面序号为优先级1-4,优先级递减 1.java.lang 1) Obj ...

随机推荐

  1. Linux Cgroup v1(中文翻译)(3):CPU Accounting Controller

    英文原文: https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cpuacct.html CPU Accounting Contr ...

  2. 互联网公司目标管理OKR和绩效考核的误区

    最近看了一篇关于「谷歌放弃OKR,转向全新的GRAD系统」的文章,我转到了研发效能DevOps的微信群里,结果引起了大家热烈的讨论,正好我们也在使用 OKR,所以也来谈谈我的理解以及我们应用起来的实际 ...

  3. Docker容器手动安装mysql(国内镜像)

    Docker手动安装mysql 1.创建centos镜像的容器 [root@localhost Tools]# docker run -i -d -h zabbix --name zabbix -p ...

  4. Acwing 1927 自动补全(知识点:hash,二分,排序)

    读完题目第一想法是trie树 ,不过好像没怎么做过trie树的题,看y总给的知识点是二分排序,所以就有了如下思路: 但是但是,看完其他题解之后才坚定了我的想法,原来真的是这样排序,暴力啊! 具体步骤 ...

  5. JS:eval

    定义和用法: eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行.eval()函数并不会创建一个新的作用域,并且它的作用域就是它所在的作用域. 如果参数是一个表达式,eva ...

  6. 实现领域驱动设计 - 使用ABP框架 - 解决方案概览

    .NET解决方案的分层 下图显示了使用ABP的 应用启动模板 创建的Visual Studio解决方案: 解决方案名称为问题跟踪,它由多个项目组成.通过考虑DDD原则以及开发和部署实践,该解决方案是分 ...

  7. Mysql安装配置以及解决重装Mysql时忘记root password问题

    目录 1.Mysql安装以及环境变量配置 重装Mysql时忘记root password问题 1.Mysql安装以及环境变量配置 官网安装:​​​​​​https://www.mysql.com/ 按 ...

  8. 《A Neural Algorithm of Artistic Style》理解

    在美术中,特别是绘画,人类掌握了通过在图像的内容和风格间建立复杂的相互作用从而创造独特的视觉体验的技巧.到目前为止,这个过程的算法基础是未知的,也没有现存的人工系统拥有这样的能力.然而在视觉感知的其他 ...

  9. 小米社区APP深度体验

    小米社区APP深度体验 版本:3.0.210928 BUG 1,在暗黑模式下,会员一栏中的成就等级小字未作深色模式调整,从而造成文字难于识别. 2,在暗黑模式下,会员页中底部的会员产品首页视觉没有完美 ...

  10. 2022宁波市第五届网络安全大赛MISC方向部分wp

    BlackAndWhite 1. 得到了三百多张黑白颜色的图片,将白色图片转为数字0,黑色图片转为数字1,得到二进制字符串 01100110011011000110000101100111011110 ...