Por que a JVM não falhar quando entrar recursão infinita?

St.Antario:

Eu estou escrevendo uma biblioteca compartilhada para ser carregado para o JVM eo comportamento abaixo tem me preso. Aqui estão as minhas classes Java:

package com.test;

public class UnixUtil {
    static {
        System.loadLibrary("myfancylibrary");
    }
    static native int openReadOnlyFd(String path);
    static native int closeFd(int fd);
}

public class Main {

    public static void main(String[] args){
        int fd = UnixUtil.openReadOnlyFd("/tmp/testc");
        UnixUtil.closeFd(fd);
    }
}

E a biblioteca a ser carregada se parece com:

test_jni.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_test_UnixUtil */

#ifndef _Included_com_test_UnixUtil
#define _Included_com_test_UnixUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_test_UnixUtil
 * Method:    openReadOnlyFd
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_test_UnixUtil_openReadOnlyFd
  (JNIEnv *, jclass, jstring);

/*
 * Class:     com_test_UnixUtil
 * Method:    closeFd
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_com_test_UnixUtil_closeFd
  (JNIEnv *, jclass, jint);

#ifdef __cplusplus
}
#endif
#endif

test_jni.c

#include "test_jni.h"
#include "fs.h"


JNIEXPORT jint JNICALL Java_com_test_UnixUtil_openReadOnlyFd
  (JNIEnv *e, jclass jc, jstring path){
  const char *const native_path = ((*e) -> GetStringUTFChars)(e, path, NULL);
  int fd = read_only_open(native_path);
  ((*e) -> ReleaseStringUTFChars)(e, path, native_path);
  return fd;
}


JNIEXPORT jint JNICALL Java_com_test_UnixUtil_closeFd
   (JNIEnv *e, jclass jc, jint fd){
   printf("Closing files descriptord %d... \n", fd);
   return close(fd);
}

fs.h

#ifndef FS_H
#define FS_H

int read_only_open(const char *path);

int close(int fd);

#endif //FS_H

fs.c

#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <sys/fcntl.h>

#include "fs.h"

int read_only_open(const char *path){
    printf("Entering %s.%s:%d\n", __FILE__, __func__, __LINE__);
    int fd = open(path, O_RDONLY);
    return fd;
}

int close(int fd){ //Java_com_test_UnixUtil_closeFd does not invoke this function
    printf("Entering %s.%s:%d\n", __FILE__, __func__, __LINE__);
    int close_result = close(fd);
    return close_result;
}

Ao compilar e executar este Mainclasse a JVM não falhar . Ele simplesmente não entrar na função fs.h::close(int). Em vez disso, stdlib's close é chamado como pode ser visto na GDB:

Thread 2 "java" hit Breakpoint 1, Java_com_test_UnixUtil_closeFd (e=<optimized out>,
    jc=<optimized out>, fd=4) at /home/rjlomov/test_jni/src/main/java/com/test/lib/test_jni.c:17
17        return close(fd);
(gdb) step
18      }
(gdb) 
17        return close(fd);
(gdb) 
__close (fd=4) at ../sysdeps/unix/sysv/linux/close.c:27
27      ../sysdeps/unix/sysv/linux/close.c: No such file or directory.
(gdb) 
26      in ../sysdeps/unix/sysv/linux/close.c

Correndo objdump -dS libmyfancylibrary.somostra que

JNIEXPORT jint JNICALL Java_com_test_UnixUtil_closeFd                                                                                                                                                              
  (JNIEnv *e, jclass jc, jint fd){                                                                                                                                                                                 
 7d0:   53                      push   %rbx                                                                                                                                                                        
}   

//...

  return close(fd);                                                                                                                                                                                                
 7e9:   e9 62 fe ff ff          jmpq   650 <close@plt>   // <--- PLT section,
                                      // resolved by linker to stdlib::close?                                                                                                                                                         
 7ee:   66 90                   xchg   %ax,%ax        

PERGUNTA: Por que éstdlib::closechamado emJava_com_test_UnixUtil_closeFdvez defs.c::close(int)? A única coisa que posso imaginar é a JVM tem o seu próprio vinculador dinâmico que faz o trabalho ...

apangin:

Desde que você está compilando uma biblioteca compartilhada, ea função close()não é static, o compilador faz uma chamada indireta throught a Tabela Linkage Procedimento (PLT). Ao desmontar a biblioteca você provavelmente verá uma instrução

    call <close@plt>

Quando myfancylibraryé carregado, o processo já tem a implementação closeda libc, de modo que o liker dinâmica atualiza PLT para apontar para a versão de libc de close().

Acho que você gosta

Origin http://43.154.161.224:23101/article/api/json?id=153924&siteId=1
Recomendado
Clasificación