最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2023年07月30日 11:14:03   作者:darcy_yuan  
眾所周知,Java是一門跨平臺語言,針對不同的操作系統(tǒng)有不同的實(shí)現(xiàn),下面小編就來從一個(gè)非常簡單的api調(diào)用帶大家來看看Java具體是怎么做的吧

1.前言

眾所周知,Java是一門跨平臺語言,針對不同的操作系統(tǒng)有不同的實(shí)現(xiàn)。本文從一個(gè)非常簡單的api調(diào)用來看看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),此文件定義了對應(yīng)文件的native調(diào)用.

// FileInputStream.c
JNIEXPORT jint JNICALL
Java_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 對典型的四種unix like的系統(tǒng)(bsd, linux, macosx, solaris), 以及windows 提供了特殊實(shí)現(xiàn)。share是公用部分。

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

// FileInputStream.c
JNIEXPORT void JNICALL
Java_java_io_FileInputStream_initIDs(JNIEnv *env, jclass fdClass) {
    fis_fd = (*env)->GetFieldID(env, fdClass, "fd", "Ljava/io/FileDescriptor;"); /* fd field,后面用來獲取 fd */
}

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

// ioutil.c
jint
readBytes(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ū)不足,動態(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.c
ssize_t
handleRead(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.c
JNIEXPORT
jint
handleRead(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 JNICALL
JNU_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 JNICALL
JNU_ThrowNullPointerException(JNIEnv *env, const char *msg)
{
    JNU_ThrowByName(env, "java/lang/NullPointerException", msg);
}

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

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

4.總結(jié)

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

到此這篇關(guān)于詳解Java的readBytes是怎么實(shí)現(xiàn)的的文章就介紹到這了,更多相關(guān)Java readBytes內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot 2.0 整合sharding-jdbc中間件實(shí)現(xiàn)數(shù)據(jù)分庫分表

    SpringBoot 2.0 整合sharding-jdbc中間件實(shí)現(xiàn)數(shù)據(jù)分庫分表

    這篇文章主要介紹了SpringBoot 2.0 整合sharding-jdbc中間件,實(shí)現(xiàn)數(shù)據(jù)分庫分表,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下
    2019-06-06
  • Spring Security中的 @PreAuthorize 注解使用方法和示例代碼

    Spring Security中的 @PreAuthorize 注解使用方法和示例代碼

    @PreAuthorize是SpringSecurity中用于方法級權(quán)限控制的重要注解,本文詳細(xì)介紹了@PreAuthorize的使用方法,通過合理使用@PreAuthorize,可以實(shí)現(xiàn)細(xì)粒度的權(quán)限控制,確保應(yīng)用程序的安全性,感興趣的朋友跟隨小編一起看看吧
    2026-01-01
  • Java實(shí)現(xiàn)Excel表單控件的添加與刪除

    Java實(shí)現(xiàn)Excel表單控件的添加與刪除

    本文通過Java代碼示例介紹如何在Excel表格中添加表單控件,包括文本框、單選按鈕、復(fù)選框、組合框、微調(diào)按鈕等,以及如何刪除Excel中的指定表單控件,需要的可以參考一下
    2022-05-05
  • SpringBoot集成jersey打包jar找不到class的處理方法

    SpringBoot集成jersey打包jar找不到class的處理方法

    這篇文章主要介紹了SpringBoot集成jersey打包jar找不到class的處理方法,文中通過代碼示例介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-03-03
  • java動態(tài)代理示例分享

    java動態(tài)代理示例分享

    這篇文章主要介紹了java動態(tài)代理示例,需要的朋友可以參考下
    2014-02-02
  • Java編程實(shí)現(xiàn)二項(xiàng)分布的采樣或抽樣實(shí)例代碼

    Java編程實(shí)現(xiàn)二項(xiàng)分布的采樣或抽樣實(shí)例代碼

    這篇文章主要介紹了Java編程實(shí)現(xiàn)二項(xiàng)分布的采樣或抽樣實(shí)例代碼,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • JAVA如何判斷上傳文件后綴名是否符合規(guī)范MultipartFile

    JAVA如何判斷上傳文件后綴名是否符合規(guī)范MultipartFile

    這篇文章主要介紹了JAVA判斷上傳文件后綴名是否符合規(guī)范MultipartFile,文中通過實(shí)例代碼介紹了java實(shí)現(xiàn)對上傳文件做安全性檢查,需要的朋友可以參考下
    2023-11-11
  • Spring Boot 中使用 Drools 規(guī)則引擎的完整步驟

    Spring Boot 中使用 Drools 規(guī)則引擎的完整步驟

    規(guī)則引擎主要用于將業(yè)務(wù)邏輯從應(yīng)用程序代碼中分離出來,提高系統(tǒng)的靈活性和可維護(hù)性,規(guī)則引擎通過預(yù)定義的規(guī)則來處理輸入數(shù)據(jù)并做出相應(yīng)的決策,從而實(shí)現(xiàn)業(yè)務(wù)邏輯的自動化和動態(tài)調(diào)整,本文給大家介紹Spring Boot中使用 Drools 規(guī)則引擎的指南,感興趣的朋友一起看看吧
    2025-04-04
  • Java 日志中 Marker 的使用示例詳解

    Java 日志中 Marker 的使用示例詳解

    Marker是SLF4J(以及Logback、Log4j 2)提供的一個(gè)接口,它本質(zhì)上是一個(gè)命名對象,你可以把它想象成一個(gè)可以附加到日志語句上的"標(biāo)簽"或"戳記",本文給大家介紹Java日志中Marker的使用示例,感興趣的朋友跟隨小編一起看看吧
    2025-09-09
  • Spring無法解決循環(huán)依賴的五種場景分析

    Spring無法解決循環(huán)依賴的五種場景分析

    本文詳細(xì)分析Spring框架中五類循環(huán)依賴問題(構(gòu)造器注入、原型作用域、@Async、配置類、BeanPostProcessor),提出應(yīng)急方案如@Lazy、重構(gòu)設(shè)計(jì),并強(qiáng)調(diào)通過單一職責(zé)、依賴倒置等設(shè)計(jì)原則避免循環(huán)依賴,需要的朋友可以參考下
    2025-05-05

最新評論

蓬溪县| 运城市| 南投县| 临桂县| 汉阴县| 西贡区| 文水县| 新宾| 海宁市| 霍林郭勒市| 丰台区| 米脂县| 株洲市| 固原市| 平阴县| 灌南县| 云霄县| 石棉县| 宜昌市| 集贤县| 正镶白旗| 九江县| 天台县| 延寿县| 印江| 务川| 贵州省| 靖西县| 黄冈市| 蒙阴县| 吉林省| 桐庐县| 湘潭市| 东城区| 宁波市| 湘阴县| 理塘县| 泸水县| 本溪| 麦盖提县| 临邑县|