Source
We need to track the Nativie Implementation of FileInputStream's Read and start to take a detour. The implementation of FileInputStream in the Java project is different from that in the Android project. In addition, the analytics in http://blog.chinaunix.net/uid-26926660-id-3326678.htmlis correct.
Java. io. FileInputStream
@ Override public int read () throws IOException {return Streams. readSingleByte (this );}
@ Override public int read (byte [] buffer, int byteOffset, int byteCount) throws IOException {return IoBridge. read (fd, buffer, byteOffset, byteCount );}
Libcore. io. StreamsHttp://grepcode.com/file/repo1.maven.org/maven2/com.google.okhttp/okhttp/20120626/libcore/io/Streams.java
Public static int readSingleByte (InputStream in) throws IOException {byte [] buffer = new byte [1]; int result = in. read (buffer, 0, 1); // in. read ()-> FileInputStream. read-> IoBridge. read return (result! =-1 )? Buffer [0] & 0xff:-1;} finally calls IoBridge. read (FileDescriptor fd, byte [] bytes, int byteOffset, int byteCount)
Libcore. io. ioBridgeHttps://android.googlesource.com/platform/libcore/+/796f0d5a4e7b83c3efc5e587b6766977dc20b0c3/luni/src/main/java/libcore/io/IoBridge.java
Public static int read (FileDescriptor fd, byte [] bytes, int byteOffset, int byteCount) throws IOException {Arrays. checkOffsetAndCount (bytes. length, byteOffset, byteCount); check whether the array is out of bounds if (byteCount = 0) {return 0;} try {int readCount = Libcore. OS. read (fd, bytes, byteOffset, byteCount); if (readCount = 0) {return-1;} return readCount;} catch (ErrnoException errnoException) {if (errnoException. errno = EAGAIN) {// This error code is returned when the non-blocking thread in Linux executes blocking tasks, the error code is native implementation // We return 0 rather than throw if we try to read from an empty non-blocking pipe. return 0;} throw errnoException. rethrowAsIOException ();}}
Java. util. ArraysHttps://android.googlesource.com/platform/libcore/+/2bad9bff258de6275bd3847e5e9f3169b0a93c61/luni/src/main/java/java/util/Arrays.javapublic static void checkoffsetandcount (INT arraylength, int offset, int count) {If (offset | count) <0 | Offset> arraylength | arraylength-offset <count) {Throw new arrayindexoutofboundsexception (arraylength, offset, count );}}
OsConstants. javaHttps://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/libcore/io/OsConstants.java
Public static final int EAGAIN = placeholder (); private static native void initConstants (); // A hack to avoid these constants being inlined by javac... private static int placeholder () {return 0 ;}//... because we want to initialize them at runtime. static {initConstants ();}
Libcore_io_OsConstants.cppHttps://android.googlesource.com/platform/libcore/+/2bad9bff258de6275bd3847e5e9f3169b0a93c61/luni/src/main/native/libcore_io_OsConstants.cpp#include <errno. h> http://baike.baidu.com/view/5806465.htm#define EAGAIN 11/* Try again */
Libcore. io. LibcoreHttp://grepcode.com/file/repo1.maven.org/maven2/org.robovm/robovm-rt/0.0.2/libcore/io/Libcore.java#Libcore
Package libcore. io;
Public final class Libcore {private Libcore (){}
Public static OS OS = new BlockGuardOs (new Posix ());}
BlockGuardOsAndroid/platform/libcore/2bad9bff258de6275bd3847e5e9f00009b0a93c61/./luni/src/main/Java/libcore/IO/blockguardos. Java
@ Override public int read (filedescriptor FD, byte [] bytes, int byteoffset, int bytecount) throws errnoexception {blockguard. getthreadpolicy (). onreadfromdisk (); // blockguard. getthreadpolicy () is a singleton return OS. read (FD, bytes, byteoffset, bytecount); // read in POSIX}
Libcore. io. PosixHttps://android.googlesource.com/platform/libcore/+/6c9b5377550a9649ed1532d1fcdfeba116c74ead/luni/src/main/java/libcore/io/Posix.java public int read (FileDescriptor fd, byte [] bytes, int byteOffset, int byteCount) throws ErrnoException {// This indirection isn' t strictly necessary, but ensures that our public interface is type safe. return readBytes (fd, bytes, byteOffset, byteCount);} private native int readBytes (FileDescriptor fd, Object buffer, int offset, int byteCount) throws ErrnoException;
Src/main/native/libcore_io_Posix.cpp
Https://android.googlesource.com/platform/libcore/+/721ceca2a52a3c27aa751476c8562e1e68088e15/luni/src/main/native/libcore_io_Posix.cpp
# Include <unistd. h> # include "ScopeBytes. h"
Static jint Posix_readBytes (JNIEnv * env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount) {bytes (env, javaBytes); // ScopeBytes. if (bytes. get () = NULL) {return-1;} int fd = jniGetFDFromFileDescriptor (env, javaFd); return throwIfMinusOne (env, "read", TEMP_FAILURE_RETRY (read (fd, bytes. get () + byteOffset, byteCount )));}
1. ScopedBytesRW bytes (env, javaBytes); ScopeBytes. h has defined https://android.googlesource.com/platform/libnativehelper/+/3d9d2148155c2e0b3bf51cd548f58f93d1199a4e/include/nativehelper/ScopedBytes.h2. throwIfMinusOne and bytes. read (fd, bytes. get () + byteOffset, byteCount) is c's Library Function
ThrowIfMinusOne
Template <typename rc_t> static rc_t throwifminusone (jnienv * ENV, const char * Name, rc_t RC) {If (rc = rc_t (-1) {throwerrnoexception (ENV, name);} return RC ;}
Static void throwerrnoexception (jnienv * ENV, const char * Name) {int errnum = errno;
Jthrowable cause = NULL; If (env-> exceptioncheck () {cause = env-> exceptionoccurred (); env-> exceptionclear ();}
Scopedlocalref <jstring> javaname (ENV, env-> newstringutf (name); If (javaname. get () = NULL) {// not really much we can do here. we're probably dead in the water, // but let's try to stumble on... env-> exceptionclear ();}
Jobject exception; If (cause! = NULL) {static jmethodid ctor = env-> getmethodid (jniconstants: errnoexceptionclass, "<init>", "(ljava/lang/string; iljava/lang/throwable ;) V "); Exception = env-> newobject (jniconstants: errnoexceptionclass, ctor, javaname. get (), errnum, cause);} else {static jmethodid ctor = env-> getmethodid (jniconstants: errnoexceptionclass, "<init>", "(ljava/lang/string; i) V "); Exception = env-> newobject (jniconstants: errnoexceptionclass, ctor, javaname. get (), errnum);} env-> throw (reinterpret_cast <jthrowable> (exception ));}
TEMP_FAILURE_RETRY
Unistd. h, http://sinf1252.info.ucl.ac.be/usr/include/unistd.h.html# define TEMP_FAILURE_RETRY (expression) \ (_ extension _ \ ({long int _ result; \ do _ result = (long int) (expression ); \ while (_ result =-1L & errno = EINTR); \ _ result;}) # endif
Link to this article
Http://blog.csdn.net/xiaodongrush/article/details/10004997