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

更多相关文章

  1. ant 编译android工程
  2. android : 加快eclipse下android工程编译速度
  3. 我的Android最佳实践-ADT
  4. Android(安卓)Annotations 学习之路(二)解决Library工程使用AA报错
  5. 从Eclipse迁移到Android(安卓)Stdio中
  6. AndEngine引擎学习之环境配置以及示例修改
  7. Cocos2d-x学习之创建Android工程和编译
  8. Android(安卓)TV 开发简介
  9. Android如何将程序打成jar包 ,并使用jar包

随机推荐

  1. 【转】Android中对Log日志文件的分析
  2. Android DisplayMetrics类简介
  3. Android SDK Platforms 提取下载
  4. 如何去写 Android(安卓)init.rc
  5. android 条码识别软件开发全解析(续1详解
  6. Android 学习笔记【基础扫盲篇】
  7. Android(安卓)UI布局优化的要点
  8. android 联系人详解
  9. Android中10个成功的开源项目
  10. Android推送通知的实现--Android推送通知