FileInputStream 和 FileOutputStream 源码精髓

1. 构造 FileInputStream 对象,最终调用本地方法:jdk 源码   

private native void open0(String name) throws FileNotFoundException;

真实接口如下:openjdk jvm 源码:

JNIEXPORT void JNICALL
Java_java_io_FileInputStream_open0(JNIEnv *env, jobject this, jstring path) {
    fileOpen(env, this, path, fis_fd, O_RDONLY);}
fileOpen 最后调用 posix open 方法,这里 O_RDONLY 表示以只读的方式打开文件。
2. read 方法:
private native int read0() throws IOException;

真实接口如下:openjdk jvm  源码

JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_read0(JNIEnv *env, jobject this) {
    return readSingle(env, this, fis_fd);
}

JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_readBytes(JNIEnv *env, jobject this,
        jbyteArray bytes, jint off, jint len) {
    return readBytes(env, this, bytes, off, len, fis_fd);
}

这里 fis_fd, 通过 FileDescriptor 对象获取,值是构造 FileInputStream 对象时获得的。所以 FileInputStream 作用就是 以只读方式打开文件并获取文件描述符。

2. 构造 FileOutputStream 对象,jdk 源码

   private void open(String name, boolean append)
        throws FileNotFoundException {
        open0(name, append);
    }

append 是否以追加的方式打开文件,hostspot jvm源码 

JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_open0(JNIEnv *env, jobject this,
                                    jstring path, jboolean append) {
    fileOpen(env, this, path, fos_fd,
             O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC));
}
默认以只写,或者创建新的,或者追加,或者截取的方式打开文件,同样也会获取文件描述符。
wirte jdk 源码
 private native void writeBytes(byte b[], int off, int len, boolean append)
        throws IOException;

hostspot jvm 源码

JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_writeBytes(JNIEnv *env,
    jobject this, jbyteArray bytes, jint off, jint len, jboolean append) {
    writeBytes(env, this, bytes, off, len, append, fos_fd);
}
结论: 构造 FileInputStream 或者 FileOutputStream 对象作用是打开文件并获取文件描述符。读写都调用 posix 系统调用,都是阻塞的。读写都是并发不安全的,需要用户自己保证并发
安全性。以 append 方式写是同步的,影响其它线程读。




原文地址:https://www.cnblogs.com/wudeyun/p/13833263.html