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 方式写是同步的,影响其它线程读。