[Android] FileInputStream跟蹤

來源:互聯網
上載者:User

源起

    需要跟蹤FileInputStream的Read的Nativie實現,開始走了彎路,Java工程下的FileInputStream實現與Android工程的實現不同。另外,http://blog.chinaunix.net/uid-26926660-id-3326678.html中分析的不錯。

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;}最終還是調用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); 檢查數組是否越界        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) { // Linux中非阻塞線程裡面執行阻塞工作,會有這樣的錯誤碼,該錯誤碼是native實現                // 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 / 2bad9bff258de6275bd3847e5e9f3169b0a93c61 / . / 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()是一個單例    return os.read(fd, bytes, byteOffset, byteCount); // 使用的是Posix中的read} 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) {    ScopedBytesRW bytes(env, javaBytes); // ScopeBytes.h中有定義    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中有定義https://android.googlesource.com/platform/libnativehelper/+/3d9d2148155c2e0b3bf51cd548f58f93d1199a4e/include/nativehelper/ScopedBytes.h2. throwIfMinusOne和TEMP_FAILURE_RETRY3. read(fd, bytes.get() + byteOffset, byteCount)就是c的庫函數 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

本文連結

    http://blog.csdn.net/xiaodongrush/article/details/10004997

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.