最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Java的readBytes是怎么實(shí)現(xiàn)的?

2023-07-30 15:15 作者:Cpp程序員  | 我要投稿

1.前言

眾所周知,Java是一門跨平臺(tái)語(yǔ)言,針對(duì)不同的操作系統(tǒng)有不同的實(shí)現(xiàn)。本文從一個(gè)非常簡(jiǎn)單的api調(diào)用來(lái)看看Java具體是怎么做的.

2.源碼分析

從FileInputStream.java中看到readBytes最后是native調(diào)用

/** ? ? * 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; // native調(diào)用 ? ?/** ? ? * 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); ? ?}

從jdk源碼中,我們找到FileInputStream.c(/jdk/src/share/native/java/io),此文件定義了對(duì)應(yīng)文件的native調(diào)用.

// FileInputStream.cJNIEXPORT 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); }

我們觀察下當(dāng)前的目錄,可以看到j(luò)ava 對(duì)典型的四種unix like的系統(tǒng)(bsd, linux, macosx, solaris), 以及windows 提供了特殊實(shí)現(xiàn)。share是公用部分。

在頭部獲取文件fd field (fd 是非負(fù)正整數(shù),用來(lái)標(biāo)識(shí)打開(kāi)文件)

// FileInputStream.cJNIEXPORT void JNICALLJava_java_io_FileInputStream_initIDs(JNIEnv *env, jclass fdClass) { ? ?fis_fd = (*env)->GetFieldID(env, fdClass, "fd", "Ljava/io/FileDescriptor;"); /* fd field,后面用來(lái)獲取 fd */}

?繼續(xù)調(diào)用readBytes

// ioutil.cjintreadBytes(JNIEnv *env, jobject this, jbyteArray bytes, ? ? ? ? ?jint off, jint len, jfieldID fid){ ? ?jint nread; ? ?char stackBuf[BUF_SIZE]; ? ?char *buf = NULL; ? ?FD fd; ? ?if (IS_NULL(bytes)) { ? ? ? ?JNU_ThrowNullPointerException(env, NULL); ? ? ? ?return -1; ? ?} ? ?if (outOfBounds(env, off, len, bytes)) { /* 越界判斷 */ ? ? ? ?JNU_ThrowByName(env, "java/lang/IndexOutOfBoundsException", NULL); ? ? ? ?return -1; ? ?} ? ?if (len == 0) { ? ? ? ?return 0; ? ?} else if (len > BUF_SIZE) { ? ? ? ?buf = malloc(len); /* 緩沖區(qū)不足,動(dòng)態(tài)分配內(nèi)存 */ ? ? ? ?if (buf == NULL) { ? ? ? ? ? ?JNU_ThrowOutOfMemoryError(env, NULL); ? ? ? ? ? ?return 0; ? ? ? ?} ? ?} else { ? ? ? ?buf = stackBuf; ? ?} ? ?fd = GET_FD(this, fid); /* 獲取fd */ ? ?if (fd == -1) { ? ? ? ?JNU_ThrowIOException(env, "Stream Closed"); ? ? ? ?nread = -1; ? ?} else { ? ? ? ?nread = IO_Read(fd, buf, len); /* 執(zhí)行read,系統(tǒng)調(diào)用 */ ? ? ? ?if (nread > 0) { ? ? ? ? ? ?(*env)->SetByteArrayRegion(env, bytes, off, nread, (jbyte *)buf); ? ? ? ?} else if (nread == -1) { ? ? ? ? ? ?JNU_ThrowIOExceptionWithLastError(env, "Read error"); ? ? ? ?} else { /* EOF */ ? ? ? ? ? ?nread = -1; ? ? ? ?} ? ?} ? ?if (buf != stackBuf) { ? ? ? ?free(buf); /* 失敗釋放內(nèi)存 */ ? ?} ? ?return nread; }

我們繼續(xù)看看IO_Read的實(shí)現(xiàn),是個(gè)宏定義

#define IO_Read handleRead

handleRead有兩種實(shí)現(xiàn)

solaris實(shí)現(xiàn):

// /jdk/src/solaris/native/java/io/io_util_md.cssize_thandleRead(FD fd, void *buf, jint len){ ? ?ssize_t result; ? ?RESTARTABLE(read(fd, buf, len), result); ? ?return result; }/* * Retry the operation if it is interrupted */#define RESTARTABLE(_cmd, _result) do { \ ? ?do { \ ? ? ? ?_result = _cmd; \ ? ?} while((_result == -1) && (errno == EINTR)); \ /* 如果是中斷,則不斷重試,避免進(jìn)程調(diào)度等待*/} while(0)

read方法可以參考unix man page

windows實(shí)現(xiàn):

// jdk/src/windows/native/java/io/io_util_md.cJNIEXPORT jinthandleRead(FD fd, void *buf, jint len){ ? ?DWORD read = 0; ? ?BOOL result = 0; ? ?HANDLE h = (HANDLE)fd; ? ?if (h == INVALID_HANDLE_VALUE) { ? ? ? ?return -1; ? ?} ? ?result = ReadFile(h, ? ? ? ? ?/* File handle to read */ ? ? ? ? ? ? ? ? ? ? ?buf, ? ? ? ?/* address to put data */ ? ? ? ? ? ? ? ? ? ? ?len, ? ? ? ?/* number of bytes to read */ ? ? ? ? ? ? ? ? ? ? ?&read, ? ? ?/* number of bytes read */ ? ? ? ? ? ? ? ? ? ? ?NULL); ? ? ?/* no overlapped struct */ ? ?if (result == 0) { ? ? ? ?int error = GetLastError(); ? ? ? ?if (error == ERROR_BROKEN_PIPE) { ? ? ? ? ? ?return 0; /* EOF */ ? ? ? ?} ? ? ? ?return -1; ? ?} ? ?return (jint)read; }

3.java異常初探

// jdk/src/share/native/common/jni_util.c/** * Throw a Java exception by name. Similar to SignalError. */JNIEXPORT void JNICALLJNU_ThrowByName(JNIEnv *env, const char *name, const char *msg){ ? ?jclass cls = (*env)->FindClass(env, name); ? ?if (cls != 0) /* Otherwise an exception has already been thrown */ ? ? ? ?(*env)->ThrowNew(env, cls, msg); /* 調(diào)用JNI 接口*/}/* JNU_Throw common exceptions */JNIEXPORT void JNICALLJNU_ThrowNullPointerException(JNIEnv *env, const char *msg){ ? ?JNU_ThrowByName(env, "java/lang/NullPointerException", msg); }

最后是調(diào)用JNI:

// hotspot/src/share/vm/prims/jni.hjint ThrowNew(jclass clazz, const char *msg) { ? ? ? ?return functions->ThrowNew(this, clazz, msg); ? ?} jint (JNICALL *ThrowNew) ? ? ?(JNIEnv *env, jclass clazz, const char *msg);

4.總結(jié)

很多高級(jí)語(yǔ)言,有著不同的編程范式,但是歸根到底還是(c語(yǔ)言)系統(tǒng)調(diào)用,c語(yǔ)言能夠在更低的層面做非常多的優(yōu)化。如果我們了解了這些底層的系統(tǒng)調(diào)用,就能看到問(wèn)題的本質(zhì)。

本文沒(méi)有對(duì)JNI 做深入分析,后續(xù)繼續(xù)解析。


Java的readBytes是怎么實(shí)現(xiàn)的?的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
阳西县| 堆龙德庆县| 高安市| 将乐县| 依兰县| 吴堡县| 杭锦后旗| 泾川县| 藁城市| 永修县| 寿宁县| 华亭县| 东明县| 左云县| 天峨县| 瑞昌市| 尼木县| 监利县| 罗定市| 临高县| 南岸区| 上思县| 都匀市| 云林县| 定结县| 越西县| 筠连县| 沙雅县| 横峰县| 平阴县| 石狮市| 阿拉善左旗| 邵阳县| 临泽县| 汝阳县| 岳池县| 元朗区| 博乐市| 塔城市| 吉安市| 棋牌|