zoukankan      html  css  js  c++  java
  • [Android] FileInputStream跟踪

    1. 源起

        需要跟踪FileInputStream的Read的Nativie实现,开始走了弯路,Java工程下的FileInputStream实现与Android工程的实现不同。另外,http://blog.chinaunix.net/uid-26926660-id-3326678.html中分析的很好。


    2. java.io.FileInputStream

    import libcore.io.Libcore;
    import libcore.io.Streams; 
    @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);
    }

    继续跟踪Streams.readSingleByte和IoBridge.read


    3. libcore.io.Streams

    http://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);
        return (result != -1) ? buffer[0] & 0xff : -1;
    }
    

    这里用了InputStream.read(byte[], int, int),实际上还是调用的FileInputStream.read(byte[], int, int),最后还是调用IoBridge.read(byte[], int, int)


    4. libcore.io.ioBridge

    https://android.googlesource.com/platform/libcore/+/796f0d5a4e7b83c3efc5e587b6766977dc20b0c3/luni/src/main/java/libcore/io/IoBridge.java

        /**
         * java.io thinks that a read at EOF is an error and should return -1, contrary to traditional
         * Unix practice where you'd read until you got 0 bytes (and any future read would return -1).
         */
        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) {
                    // We return 0 rather than throw if we try to read from an empty non-blocking pipe.
                    return 0;
                }
                throw errnoException.rethrowAsIOException();
            }
        }
    


    5. libcore.io.Libcore

    http://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());
    }
    

    到这里有点断片了,BlockGuardOs里面还有一些调用,这里参考了http://blog.chinaunix.net/uid-26926660-id-3326678.html文章,read操作是由Posix实现的。


    6. Libcore.io.Posix

    https://android.googlesource.com/platform/libcore/+/6c9b5377550a9649ed1532d1fcdfeba116c74ead/luni/src/main/java/libcore/io/Posix.java    

    public int read(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException {
        if (buffer.isDirect()) {
            return readBytes(fd, buffer, buffer.position(), buffer.remaining());
        } else {
            return readBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining());
        }
    }
    
    

    到这里就是native方法了。


    7. 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);
        if (bytes.get() == NULL) {
            return -1;
        }
        int fd = jniGetFDFromFileDescriptor(env, javaFd);
        return throwIfMinusOne(env, "read", TEMP_FAILURE_RETRY(read(fd, bytes.get() + byteOffset, byteCount)));
    }
    
    

    第一:return throwIfMinusOne(env, "write", TEMP_FAILURE_RETRY(write(fd, bytes.get() + byteOffset, byteCount)));

    throwIfMinusOne与TEMP_FAILURE_RETRY是宏定义。

    write是<unistd.h>中的C语言库函数

    第二:ScopedBytesRW

    https://android.googlesource.com/platform/libnativehelper/+/3d9d2148155c2e0b3bf51cd548f58f93d1199a4e/include/nativehelper/ScopedBytes.h

    这个文件比较简单,仅仅include了JNIHelper.h,用来区分byte[]s与ByteBuffers的。

    class ScopedBytesRW : public ScopedBytes<false> {
    public:
        ScopedBytesRW(JNIEnv* env, jobject object) : ScopedBytes<false>(env, object) {}
        jbyte* get() {
            return mPtr;
        }
    };


    8. 本文链接

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

  • 相关阅读:
    Redis 安全
    Redis 数据备份与恢复
    Redis 服务器
    Redis 连接
    Redis 脚本
    Linux中使用netstat命令的基本操作,排查端口号的占用情况
    ElasticSearch 常用查询语句
    GO代码风格指南 Uber Go (转载)
    coding 注意事项(总结中)
    Byte字节
  • 原文地址:https://www.cnblogs.com/riskyer/p/3263080.html
Copyright © 2011-2022 走看看