Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 按socketRead0分配的字符串TLAB_Java_Jvm_Allocation_Async Profiler - Fatal编程技术网

Java 按socketRead0分配的字符串TLAB

Java 按socketRead0分配的字符串TLAB,java,jvm,allocation,async-profiler,Java,Jvm,Allocation,Async Profiler,环境: Linux 4.x 异步探查器1.6() OpenJDK8 申请代码: 通过SocketInputStream进行域套接字通信 行动: 使用异步探查器运行应用程序:-d 60-e alloc-f/tmp/alloc.svg 问题: 来自SocketInputStream#socketRead0的意外字符串分配 private int socketRead(FileDescriptor fd, byte b[], int off, int le

环境:

  • Linux 4.x
  • 异步探查器1.6()
  • OpenJDK8
  • 申请代码:

    通过SocketInputStream进行域套接字通信

    行动:

    使用异步探查器运行应用程序:-d 60-e alloc-f/tmp/alloc.svg

    问题:

    来自SocketInputStream#socketRead0的意外字符串分配

    private int socketRead(FileDescriptor fd,
                           byte b[], int off, int len,
                           int timeout)
        throws IOException {
        return socketRead0(fd, b, off, len, timeout);
    }
    
    private native int socketRead0(FileDescriptor fd,
                                   byte b[], int off, int len,
                                   int timeout)
    
    (青色:TLAB alloc)

    socketRead和socketRead0的JDK代码

    private int socketRead(FileDescriptor fd,
                           byte b[], int off, int len,
                           int timeout)
        throws IOException {
        return socketRead0(fd, b, off, len, timeout);
    }
    
    private native int socketRead0(FileDescriptor fd,
                                   byte b[], int off, int len,
                                   int timeout)
    
    本机套接字Impl:

    • jdk/src/solaris/native/java/net/SocketInputStream.c
    假设:

    字符串可能是通过JNI在下面代码中的某个地方在java堆中分配的,因为在字符串分配旁边的StackTrace中有一个SocketTimeoutException

    Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
                                                jobject fdObj, jbyteArray data,
                                                jint off, jint len, jint timeout)
    {
        [...]
        if (timeout) {
            nread = NET_ReadWithTimeout(env, fd, bufP, len, timeout);
            if ((*env)->ExceptionCheck(env)) {
                if (bufP != BUF) {
                    free(bufP);
                }
                return nread;
            }
        } else {
            nread = NET_Read(fd, bufP, len);
        }
        [...]
    }
    
    static int NET_ReadWithTimeout(JNIEnv *env, int fd, char *bufP, int len, long timeout) {
        int result = 0;
        long prevtime = NET_GetCurrentTime(), newtime;
        while (timeout > 0) {
            result = NET_TimeoutWithCurrentTime(fd, timeout, prevtime);
            if (result <= 0) {
                if (result == 0) {
                    JNU_ThrowByName(env, "java/net/SocketTimeoutException", "Read timed out");
                } else if (result == -1) {
                    if (errno == EBADF) {
                        JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
                    } else if (errno == ENOMEM) {
                        JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
                    } else {
                        JNU_ThrowByNameWithMessageAndLastError
                                (env, "java/net/SocketException", "select/poll failed");
                    }
                }
                return -1;
            }
            result = NET_NonBlockingRead(fd, bufP, len);
            if (result == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) {
                newtime = NET_GetCurrentTime();
                timeout -= newtime - prevtime;
                if (timeout > 0) {
                    prevtime = newtime;
                }
            } else {
                break;
            }
        }
        return result;
    }
    
    Java\u Java\u net\u SocketInputStream\u socketRead0(JNIEnv*env,jobject this,
    jobject fdObj,jbyteArray数据,
    吉特关,吉特蓝,吉特超时)
    {
    [...]
    如果(超时){
    nread=净读取超时(env、fd、bufP、len、超时);
    如果((*env)->例外检查(env)){
    如果(bufP!=BUF){
    免费(bufP);
    }
    返回nread;
    }
    }否则{
    nread=净读取(fd、bufP、len);
    }
    [...]
    }
    静态int NET_ReadWithTimeout(JNIEnv*env、int fd、char*bufP、int len、长超时){
    int结果=0;
    long prevtime=NET_GetCurrentTime(),newtime;
    同时(超时>0){
    结果=净时间超过当前时间(fd、超时、prevtime);
    如果(结果0){
    prevtime=newtime;
    }
    }否则{
    打破
    }
    }
    返回结果;
    }
    
    我搜索了C代码,没有找到任何jString分配,因此我有点想法


    有人知道字符串分配可能发生在哪里吗?

    您的假设是正确的<概要文件中的code>SocketTimeoutException说明该方法分配了一个异常对象,并且该异常对象有一个
    字符串
    消息,该消息也需要分配

    我刚刚提交了对async profiler的一个更改,它添加了
    --cstack
    选项,用于在分配分析模式下记录C堆栈和Java堆栈。证明了
    java.lang.String
    确实是从JNI
    ThrowNew
    函数分配的:


    我从master构建了异步探查器,事实上,我确实看到了与您在示例中描述的--cstack相同的行为。谢谢你的贡献。