[Android] FileInputStream跟蹤

來源:互聯網
上載者:User

1. 源起

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

 


2. java.io.FileInputStream

[java] 
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); 

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

[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; 

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] 
/**
 * 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(); 
    } 

    /**
     * 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


[java] 
package libcore.io; 
 
public final class Libcore { 
    private Libcore() { } 
 
    public static Os os = new BlockGuardOs(new Posix()); 

package libcore.io;

public final class Libcore {
    private Libcore() { }

    public static Os os = new BlockGuardOs(new Posix());
}
到這裡有點斷片了,BlockGuardOs裡面還有一些調用,
 

 


6. Libcore.io.Posix

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

[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()); 
    } 

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


[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))); 

#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的。

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

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

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.