JAVA File类 分析(四)

本文介绍了JAVA File类在Unix系统中的实现,主要关注UnixFileSystem的实例化过程以及其核心的native方法。文章指出在JDK1.7之前File类的功能相对较弱,直到JDK7才逐步完善,如查看文件是否可执行等。同时,作者认为Java的某些过度封装限制了其灵活性,与C语言相比仍有差距。
摘要由CSDN通过智能技术生成

托了好久,终于开始JAVA File 的分析,废话不说,还是先上代码

public class File
    implements Serializable, Comparable<File>
{
static private FileSystem fs = FileSystem.getFileSystem();

File 想发挥作用,就要先获取文件系统,跟进FileSystem.getFileSystem(); 看看

abstract class FileSystem {

    /**
     * Return the FileSystem object representing this platform's local
     * filesystem.
     */
    public static native FileSystem getFileSystem();

是个native方法,通过JNI找到FileSystem_md.c

#include "jni.h"
#include "jni_util.h"
#include "java_io_FileSystem.h"


JNIEXPORT jobject JNICALL
Java_java_io_FileSystem_getFileSystem(JNIEnv *env, jclass ignored)
{
    return JNU_NewObjectByName(env, "java/io/UnixFileSystem", "()V");
}
看到getFileSystem了吧
继续跟进入JNU_NewObjectByName函数

JNIEXPORT jobject JNICALL
JNU_NewObjectByName(JNIEnv *env, const char *class_name,
                    const char *constructor_sig, ...)
{
    jobject obj = NULL;

    jclass cls = 0;
    jmethodID cls_initMID;
    va_list args;

    if ((*env)->EnsureLocalCapacity(env, 2) < 0)
        goto done;

    cls = (*env)->FindClass(env, class_name);
    if (cls == 0) {
        goto done;
    }
    cls_initMID  = (*env)->GetMethodID(env, cls,
                                       "<init>", constructor_sig);
    if (cls_initMID == NULL) {
        goto done;
    }
    va_start(args, constructor_sig);
    obj = (*env)->NewObjectV(env, cls, cls_initMID, args);
    va_end(args);

 done:
    (*env)->DeleteLocalRef(env, cls);
    return obj;
}

代码就不跟了,有兴趣的同学自己跟吧,这个处理过程就是要通过传入的参数(类的路径和类名)生成类的实例。unix系统中 返回UnixFileSystem.java 类的实例,上面代码传入了“java/io/UnixFileSystem”,也就是生成UnixFileSystem的实现,也正是我们要研究的。

在这里多说一句,大家可以根据上面的代码,就能跟出一个java类的在虚拟机中实例创建过程

cls = (*env)->FindClass(env, class_name);
以上代码,在方法区,也就是永久区,找到了该要实例的类(注意是类,不是对象,对象是在堆区,实例的类指的是该类是否被虚拟机的类加载器加载)

 cls_initMID  = (*env)->GetMethodID(env, cls,
                                       "<init>", constructor_sig);
以上代码,获取方法区标识

 va_start(args, constructor_sig);
    obj = (*env)->NewObjectV(env, cls, cls_initMID, args);
    va_end(args);
以上代码,实例化类,创建类的实例---对象


这里仅仅是一个流程,并没有进去方法内,其实现过程是相当复杂的。还是不多讲了。


接着说这个被实例化的类,我还是可耻的上代码啦

package java.io;

import java.security.AccessController;
import sun.security.action.GetPropertyAction;


class UnixFileSystem extends FileSystem {

    private final char slash;
    private final char colon;
    private final String javaHome;

    public UnixFileSystem() {
        slash = AccessController.doPrivileged(
            new GetPropertyAction("file.separator")).charAt(0);
        colon = AccessController.doPrivileged(
            new GetPropertyAction("path.separator")).charAt(0);
        javaHome = AccessController.doPrivileged(
            new GetPropertyAction("java.home"));
    }
 
    public char getSeparator() {
        return slash;
    }

    public char getPathSeparator() {
        return colon;
    }

    /* A normal Unix pathname contains no duplicate slashes and does not end
       with a slash.  It may be the empty string. */

    /* Normalize the given pathname, whose length is len, starting at the given
       offset; everything before this offset is already normal. */
    private String normalize(String pathname, int len, int off) {
        if (len == 0) return pathname;
        int n = len;
        while ((n > 0) && (pathname.charAt(n - 1) == '/')) n--;
        if (n == 0) return "/";
        StringBuffer sb = new StringBuffer(pathname.length());
        if (off > 0) sb.append(pathname.substring(0, off));
        char prevChar = 0;
        for (int i = off; i < n; i++) {
            char c = pathname.charAt(i);
            if ((prevChar == '/') && (c == '/')) continue;
            sb.append(c);
            prevChar = c;
        }
        return sb.toString();
    }

   
    public String normalize(String pathname) {
        int n = pathname.length();
        char prevChar = 0;
        for (int i = 0; i < n; i++) {
            char c = pathname.charAt(i);
            if ((prevChar == '/') && (c == '/'))
                return normalize(pathname, n, i - 1);
            prevChar = c;
        }
        if (prevChar == '/') return normalize(pathname, n, n - 1);
        return pathname;
    }

    public int prefixLength(String pathname) {
        if (pathname.length() == 0) return 0;
        return (pathname.charAt(0) == '/') ? 1 : 0;
    }

    public String resolve(String parent, String child) {
        if (child.equals("")) return parent;
        if (child.charAt(0) ==
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值