美文网首页
OpenJDK源码中的头文件和宏定义

OpenJDK源码中的头文件和宏定义

作者: buzzerrookie | 来源:发表于2019-03-03 10:23 被阅读0次

    本系列使用jdk8u202-b26和64位 CentOS 7作为实验环境分析JVM。本文介绍源码中的一些重要的头文件和宏定义,jdk8u202-b26的源码下载地址为http://hg.openjdk.java.net/jdk8u/jdk8u/rev/a8b6e38ee409,下文提到的文件路径均为相对于源码根目录的路径。

    JDK中的头文件和宏定义

    jdk子目录与JNI有关的头文件有jni.h、jni_md.h等。

    jni.h

    首先来看最重要的jni.h,它的路径是jdk/src/share/javavm/export/jni.h,该文件在目录${JAVA_HOME}/include中也有出现,该文件的部分代码如下所示:

    #ifndef _JAVASOFT_JNI_H_
    #define _JAVASOFT_JNI_H_
    
    #include <stdio.h>
    #include <stdarg.h>
    
    /* jni_md.h contains the machine-dependent typedefs for jbyte, jint
       and jlong */
    
    #include "jni_md.h"
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    /*
     * JNI Types
     */
    
    #ifndef JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H
    
    typedef unsigned char   jboolean;
    typedef unsigned short  jchar;
    typedef short           jshort;
    typedef float           jfloat;
    typedef double          jdouble;
    
    typedef jint            jsize;
    
    struct _jobject;
    
    typedef struct _jobject *jobject;
    typedef jobject jclass;
    typedef jobject jthrowable;
    typedef jobject jstring;
    typedef jobject jarray;
    typedef jarray jbooleanArray;
    typedef jarray jbyteArray;
    typedef jarray jcharArray;
    typedef jarray jshortArray;
    typedef jarray jintArray;
    typedef jarray jlongArray;
    typedef jarray jfloatArray;
    typedef jarray jdoubleArray;
    typedef jarray jobjectArray;
    
    #endif /* JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H */
    
    /*
     * jboolean constants
     */
    
    #define JNI_FALSE 0
    #define JNI_TRUE 1
    
    /*
     * possible return values for JNI functions.
     */
    
    #define JNI_OK           0                 /* success */
    #define JNI_ERR          (-1)              /* unknown error */
    #define JNI_EDETACHED    (-2)              /* thread detached from the VM */
    #define JNI_EVERSION     (-3)              /* JNI version error */
    #define JNI_ENOMEM       (-4)              /* not enough memory */
    #define JNI_EEXIST       (-5)              /* VM already created */
    #define JNI_EINVAL       (-6)              /* invalid arguments */
    
    /*
     * used in RegisterNatives to describe native method name, signature,
     * and function pointer.
     */
    
    typedef struct {
        char *name;
        char *signature;
        void *fnPtr;
    } JNINativeMethod;
    
    /*
     * JNI Native Method Interface.
     */
    
    struct JNINativeInterface_;
    
    struct JNIEnv_;
    
    #ifdef __cplusplus
    typedef JNIEnv_ JNIEnv;
    #else
    typedef const struct JNINativeInterface_ *JNIEnv;
    #endif
    
    struct JNINativeInterface_ {
        void *reserved0;
        void *reserved1;
        void *reserved2;
    
        void *reserved3;
        jint (JNICALL *GetVersion)(JNIEnv *env);
    
        jclass (JNICALL *DefineClass)
          (JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
           jsize len);
        jclass (JNICALL *FindClass)
          (JNIEnv *env, const char *name);
    }
    

    该头文件定义了如下内容:

    • JNI的类型:如jboolean、jshort和jobject等;
    • 一些枚举和常量:如JNI_FALSE、JNI_TRUE和JNI函数返回值等;
    • JNI接口指针:对C语言,JNIEnv即是JNI接口指针,它指向JNINativeInterface_结构体,该结构体定义了所有JNI函数的指针,受篇幅所限,该结构体的代码没有完全列出。

    jni_md.h

    上文jni.h除了包含两个系统头文件外,紧接着便包含了jni_md.h文件,md表示machine-dependent。jni_md.h定义了平台相关的类型如jbyte、jint和jlong,还有JNIEXPORT、JNIIMPORT和JNICALL宏,因此该文件在不同平台对应的目录均有出现。不同平台该文件路径如下表所示:

    平台类型 相对路径
    Linux/Solaris jdk/src/solaris/javavm/export/jni_md.h
    Windows jdk/src/windows/javavm/export/jni_md.h
    Mac OS X jdk/src/macosx/javavm/export/jni_md.h
    • Linux下jni_md.h文件如下所示,jint即是int,若定义了_LP64那么jlong是long,否则是long long,jbyte是signed char;
    #ifndef _JAVASOFT_JNI_MD_H_
    #define _JAVASOFT_JNI_MD_H_
    
    #ifndef __has_attribute
      #define __has_attribute(x) 0
    #endif
    #if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
      #define JNIEXPORT     __attribute__((visibility("default")))
      #define JNIIMPORT     __attribute__((visibility("default")))
    #else
      #define JNIEXPORT
      #define JNIIMPORT
    #endif
    
    #define JNICALL
    
    typedef int jint;
    #ifdef _LP64 /* 64-bit Solaris */
    typedef long jlong;
    #else
    typedef long long jlong;
    #endif
    
    typedef signed char jbyte;
    
    #endif /* !_JAVASOFT_JNI_MD_H_ */
    
    • Windows下jni_md.h文件如下所示,jint即是int,jlong是__int64,jbyte是signed char。
    #ifndef _JAVASOFT_JNI_MD_H_
    #define _JAVASOFT_JNI_MD_H_
    
    #define JNIEXPORT __declspec(dllexport)
    #define JNIIMPORT __declspec(dllimport)
    #define JNICALL __stdcall
    
    typedef long jint;
    typedef __int64 jlong;
    typedef signed char jbyte;
    
    #endif /* !_JAVASOFT_JNI_MD_H_ */
    

    JNIEXPORT、JNIIMPORT和JNICALL宏定义

    JNIEXPORT、JNIIMPORT和JNICALL宏均在jni_md.h头文件中定义:

    • Linux下,JNIEXPORT和JNIIMPORT宏定义视gcc版本而定,JNICALL宏什么也没做
    • Windows下,JNIEXPORT、JNIIMPORT和JNICALL宏都与Windows下编译器的指令有关;

    TODO 以后深究这些指令。

    JVM中的头文件和宏定义

    hotspot子目录中也有jni.h和jni_md.h头文件,其中jni.h与JDK中的相似,路径是hotspot/src/share/vm/prims/jni.h,但是jni_md.h文件有较大区别。

    jni_md.h

    jni_md.h文件路径为hotspot/src/share/vm/prims/jni_md.h,代码如下所示。为了交叉编译Hotspot,需要指定目标系统和架构,因此使用了预处理指令进行判断以包含不同平台的头文件。

    #ifdef TARGET_ARCH_x86
    # include "jni_x86.h"
    #endif
    #ifdef TARGET_ARCH_sparc
    # include "jni_sparc.h"
    #endif
    #ifdef TARGET_ARCH_zero
    # include "jni_zero.h"
    #endif
    #ifdef TARGET_ARCH_arm
    # include "jni_arm.h"
    #endif
    #ifdef TARGET_ARCH_ppc
    # include "jni_ppc.h"
    #endif
    

    jni_x86.h文件路径为hotspot/src/cpu/x86/vm/jni_x86.h,代码如下,其内容与上文JDK中的相似。

    #ifndef _JAVASOFT_JNI_MD_H_
    #define _JAVASOFT_JNI_MD_H_
    
    #if defined(SOLARIS) || defined(LINUX) || defined(_ALLBSD_SOURCE)
    
    
    // Note: please do not change these without also changing jni_md.h in the JDK
    // repository
    #ifndef __has_attribute
      #define __has_attribute(x) 0
    #endif
    #if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
      #define JNIEXPORT     __attribute__((visibility("default")))
      #define JNIIMPORT     __attribute__((visibility("default")))
    #else
      #define JNIEXPORT
      #define JNIIMPORT
    #endif
    
      #define JNICALL
      typedef int jint;
    #if defined(_LP64)
      typedef long jlong;
    #else
      typedef long long jlong;
    #endif
    
    #else
      #define JNIEXPORT __declspec(dllexport)
      #define JNIIMPORT __declspec(dllimport)
      #define JNICALL __stdcall
    
      typedef int jint;
      typedef __int64 jlong;
    #endif
    
    typedef signed char jbyte;
    
    #endif /* !_JAVASOFT_JNI_MD_H_ */
    

    宏定义

    JVM_ENTRY和JVM_END是常见的两个宏,它们定义在文件hotspot/src/share/vm/runtime/interfaceSupport.hpp中。

    • JVM_ENTRY
    #define JVM_ENTRY(result_type, header)                               \
    extern "C" {                                                         \
    result_type JNICALL header {                                       \
        JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
        ThreadInVMfromNative __tiv(thread);                              \
        debug_only(VMNativeEntryWrapper __vew;)                          \
        VM_ENTRY_BASE(result_type, header, thread)
    
    • JVM_END
    #define JVM_END } }
    

    相关文章

      网友评论

          本文标题:OpenJDK源码中的头文件和宏定义

          本文链接:https://www.haomeiwen.com/subject/ajbxjqtx.html