本站首页    管理页面    写新日志    退出


«August 2025»
12
3456789
10111213141516
17181920212223
24252627282930
31


公告

戒除浮躁,读好书,交益友


我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:邢红瑞的blog
日志总数:523
评论数量:1142
留言数量:0
访问次数:9693498
建立时间:2004年12月20日




[jvm]未公开的mustang核心秘密(三):jdk读取文件的秘密
原创空间,  软件技术,  电脑与网络

邢红瑞 发表于 2007/6/18 16:16:55

 最近做一个很简单的函数,要两个返回值,我打算有一个类封装一下返回,后来领导要求使用StringBuilder返回,不用StringBuffer,因为局部变量StringBuffer最后还是要编译为StringBuilder,因为StringBuilder没有任何同步。问了一下大家的看法,风南说InputStream 的int read(byte[] b) 从输入流中读取一定数量的字节并将其存储在缓冲区数组 b 中,也是类似的,看来有必要研究一下IO了。 InputStream类中重要的函数,只有一个抽象的有用,   public abstract int read() throws IOException;其他两个read的意义不大。 public int read(byte b[], int off, int len) throws IOException 和 public int read(byte b[]) throws IOException {    return read(b, 0, b.length);    }下面看它的子类FileInputStream的实现, /* File Descriptor - handle to the open file */    private FileDescriptor fd;这个很重要,这是文件句柄,C语言使用fopen函数的都知道。/**     * Opens the specified file for reading.     * @param name the name of the file     */    private native void open(String name) throws FileNotFoundException;    /**     * Reads a byte of data from this input stream. This method blocks     * if no input is yet available.     *     * @return     the next byte of data, or <code>-1</code> if the end of the     *             file is reached.     * @exception  IOException  if an I/O error occurs.     */    public native int read() throws IOException;    /**     * Reads a subarray as a sequence of bytes.     * @param b the data to be written     * @param off the start offset in the data     * @param len the number of bytes that are written     * @exception IOException If an I/O error has occurred.     */    private native int readBytes(byte b[], int off, int len) throws IOException;子类修改了父的实现    /**     * Reads up to <code>b.length</code> bytes of data from this input     * stream into an array of bytes. This method blocks until some input     * is available.     *     * @param      b   the buffer into which the data is read.     * @return     the total number of bytes read into the buffer, or     *             <code>-1</code> if there is no more data because the end of     *             the file has been reached.     * @exception  IOException  if an I/O error occurs.     */    public int read(byte b[]) throws IOException {    return readBytes(b, 0, b.length);    }    /**     * Reads up to <code>len</code> bytes of data from this input stream     * into an array of bytes. If <code>len</code> is not zero, the method     * blocks until some input is available; otherwise, no     * bytes are read and <code>0</code> is returned.     *     * @param      b     the buffer into which the data is read.     * @param      off   the start offset in the destination array <code>b</code>     * @param      len   the maximum number of bytes read.     * @return     the total number of bytes read into the buffer, or     *             <code>-1</code> if there is no more data because the end of     *             the file has been reached.     * @exception  NullPointerException If <code>b</code> is <code>null</code>.     * @exception  IndexOutOfBoundsException If <code>off</code> is negative,      * <code>len</code> is negative, or <code>len</code> is greater than      * <code>b.length - off</code>     * @exception  IOException  if an I/O error occurs.     */    public int read(byte b[], int off, int len) throws IOException {    return readBytes(b, off, len);    }看出readBytes是关键的所在,windows的native code中只有JNIEXPORT void JNICALLJava_java_io_FileInputStream_close0(JNIEnv *env, jobject this) {    handleClose(env, this, fis_fd);}是平台相关的。其他的在share中FileInputStream.c代码jfieldID fis_fd; /* id for jobject 'fd' in java.io.FileInputStream *//************************************************************** * static methods to store field ID's in initializers */得到fd的值,这个很重要JNIEXPORT void JNICALLJava_java_io_FileInputStream_initIDs(JNIEnv *env, jclass fdClass) {    fis_fd = (*env)->GetFieldID(env, fdClass, "fd", "Ljava/io/FileDescriptor;");}/************************************************************** * Input stream */JNIEXPORT void JNICALLJava_java_io_FileInputStream_open(JNIEnv *env, jobject this, jstring path) {    fileOpen(env, this, path, fis_fd, O_RDONLY);}JNIEXPORT jint JNICALLJava_java_io_FileInputStream_read(JNIEnv *env, jobject this) {    return readSingle(env, this, fis_fd);}JNIEXPORT jint JNICALLJava_java_io_FileInputStream_readBytes(JNIEnv *env, jobject this,    jbyteArray bytes, jint off, jint len) {    return readBytes(env, this, bytes, off, len, fis_fd);}JNIEXPORT jlong JNICALLJava_java_io_FileInputStream_skip(JNIEnv *env, jobject this, jlong toSkip) {    jlong cur = jlong_zero;    jlong end = jlong_zero;    FD fd = GET_FD(this, fis_fd);    if ((cur = IO_Lseek(fd, (jlong)0, (jint)SEEK_CUR)) == -1) {        JNU_ThrowIOExceptionWithLastError(env, "Seek error");    } else if ((end = IO_Lseek(fd, toSkip, (jint)SEEK_CUR)) == -1) {    JNU_ThrowIOExceptionWithLastError(env, "Seek error");    }    return (end - cur);}JNIEXPORT jint JNICALLJava_java_io_FileInputStream_available(JNIEnv *env, jobject this) {    jlong ret;    FD fd = GET_FD(this, fis_fd);    if (IO_Available(fd, &ret)) {        if (ret > INT_MAX) {        ret = (jlong) INT_MAX;    }    return jlong_to_jint(ret);    }    JNU_ThrowIOExceptionWithLastError(env, NULL);    return 0;}主要是readBytes的实现,打开io_util.c文件/* IO helper functions */intreadSingle(JNIEnv *env, jobject this, jfieldID fid) {    int nread;    char ret;    FD fd = GET_FD(this, fid);    nread = IO_Read(fd, &ret, 1);    if (nread == 0) { /* EOF */    return -1;    } else if (nread == JVM_IO_ERR) { /* error */    JNU_ThrowIOExceptionWithLastError(env, "Read error");    } else if (nread == JVM_IO_INTR) {        JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);    }    return ret & 0xFF;}/* The maximum size of a stack-allocated buffer. */#define BUF_SIZE 8192intreadBytes(JNIEnv *env, jobject this, jbyteArray bytes,      jint off, jint len, jfieldID fid){    int nread, datalen;    char stackBuf[BUF_SIZE];    char *buf = 0;    FD fd;    if (IS_NULL(bytes)) {    JNU_ThrowNullPointerException(env, 0);    return -1;    }    datalen = (*env)->GetArrayLength(env, bytes);    if ((off < 0) || (off > datalen) ||        (len < 0) || ((off + len) > datalen) || ((off + len) < 0)) {        JNU_ThrowByName(env, "java/lang/IndexOutOfBoundsException", 0);    return -1;    }    if (len == 0) {    return 0;    } else if (len > BUF_SIZE) {        buf = malloc(len);    if (buf == 0) {        JNU_ThrowOutOfMemoryError(env, 0);        return 0;        }    } else {        buf = stackBuf;    }    fd = GET_FD(this, fid);    nread = IO_Read(fd, buf, len);    if (nread > 0) {        (*env)->SetByteArrayRegion(env, bytes, off, nread, (jbyte *)buf);    } else if (nread == JVM_IO_ERR) {    JNU_ThrowIOExceptionWithLastError(env, "Read error");    } else if (nread == JVM_IO_INTR) { /* EOF */        JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);    } else { /* EOF */    nread = -1;    }    if (buf != stackBuf) {        free(buf);    }    return nread;}注意IO_Read在io_util_md.h做了手脚的,#define IO_Read JVM_Read其实就是JVM_Read,JVM_Read在hotspot源码中定义的  //%note jvm_r6  return (jint)hpi::read(fd, buf, nbytes);hpi定义了大量的函数  // HPI_FileInterface  static inline char*  native_path(char *path);  static inline int    file_type(const char *path);  static inline int    open(const char *name, int mode, int perm);  static inline int    close(int fd);  static inline jlong  lseek(int fd, jlong off, int whence);  static inline int    ftruncate(int fd, jlong length);  static inline int    fsync(int fd);  static inline int    available(int fd, jlong *bytes);  static inline size_t read(int fd, void *buf, unsigned int nBytes);  static inline size_t write(int fd, const void *buf, unsigned int nBytes);  static inline int    fsize(int fd, jlong *size);这就是和平台相关的代码了。window下通过HPIDECL宏转换的


阅读全文(4648) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.047 second(s), page refreshed 144763161 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号