Top


定義場所(file name)

jdk/src/share/native/common/check_code.c

名前(function name)

JNIEXPORT jboolean
VerifyClassForMajorVersion(JNIEnv *env, jclass cb, char *buffer, jint len,
                           jint major_version)
{

本体部(body)

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

        context_type context_structure;
        context_type *context = &context_structure;
        jboolean result = CC_OK;
        int i;
        int num_methods;
        int* code_lengths;
        unsigned char** code;

  {- -------------------------------------------
  (1) (デバッグ用の処理) (#ifdef DEBUG 時にのみ実行)
      ---------------------------------------- -}

    #ifdef DEBUG
        GlobalContext = context;
    #endif

  {- -------------------------------------------
  (1) (局所変数の初期化)
      ---------------------------------------- -}

        memset(context, 0, sizeof(context_type));
        context->message = buffer;
        context->message_buf_len = len;

        context->env = env;
        context->class = cb;

        /* Set invalid method/field index of the context, in case anyone
           calls CCerror */
        context->method_index = -1;
        context->field_index = -1;

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

        /* Don't call CCerror or anything that can call it above the setjmp! */

  {- -------------------------------------------
  (1) まず setjmp() で大域脱出点を設定した後, 以下の if ブロック内で verification を行う.
      (エラーが起こった場合には longjmp() で脱出)
      ---------------------------------------- -}

        if (!setjmp(context->jump_buffer)) {

    {- -------------------------------------------
  (1.1) (変数宣言など)
        ---------------------------------------- -}

            jclass super;

    {- -------------------------------------------
  (1.1) (局所変数の初期化) (#TODO)
        (エラーが起こった場合は longjmp() で脱出)
        ---------------------------------------- -}

            CCinit(context);                /* initialize heap; may throw */

    {- -------------------------------------------
  (1.1) (局所変数の初期化) (#TODO)
        (エラーが起こった場合は longjmp() で脱出)
        ---------------------------------------- -}

            initialize_class_hash(context);

    {- -------------------------------------------
  (1.1) (局所変数の初期化) (#TODO)
        (エラーが起こった場合は, CCout_of_memory() を呼んで longjmp() で脱出)
        ---------------------------------------- -}

            context->major_version = major_version;
            context->nconstants = JVM_GetClassCPEntriesCount(env, cb);
            context->constant_types = (unsigned char *)
                malloc(sizeof(unsigned char) * context->nconstants + 1);

            if (context->constant_types == 0)
                CCout_of_memory(context);

    {- -------------------------------------------
  (1.1) (局所変数の初期化) (#TODO)
        (エラーが起こった場合は, CCout_of_memory() を呼んで longjmp() で脱出)
        ---------------------------------------- -}

            JVM_GetClassCPTypes(env, cb, context->constant_types);

            if (context->constant_types == 0)
                CCout_of_memory(context);

    {- -------------------------------------------
  (1.1) (局所変数の初期化) (#TODO)
        ---------------------------------------- -}

            context->object_info =
                make_class_info_from_name(context, "java/lang/Object");
            context->string_info =
                make_class_info_from_name(context, "java/lang/String");
            context->throwable_info =
                make_class_info_from_name(context, "java/lang/Throwable");
            context->cloneable_info =
                make_class_info_from_name(context, "java/lang/Cloneable");
            context->serializable_info =
                make_class_info_from_name(context, "java/io/Serializable");

            context->currentclass_info = make_loadable_class_info(context, cb);

    {- -------------------------------------------
  (1.1) (局所変数の初期化?) (#TODO)
        (エラーが起こった場合は, CCout_of_memory() を呼んで longjmp() で脱出)
        ---------------------------------------- -}

            super = (*env)->GetSuperclass(env, cb);

            if (super != 0) {
                fullinfo_type *gptr;
                int i = 0;

                context->superclass_info = make_loadable_class_info(context, super);

                while(super != 0) {
                    jclass tmp_cb = (*env)->GetSuperclass(env, super);
                    (*env)->DeleteLocalRef(env, super);
                    super = tmp_cb;
                    i++;
                }
                (*env)->DeleteLocalRef(env, super);
                super = 0;

                /* Can't go on context heap since it survives more than
                   one method */
                context->superclasses = gptr =
                    malloc(sizeof(fullinfo_type)*(i + 1));
                if (gptr == 0) {
                    CCout_of_memory(context);
                }

                super = (*env)->GetSuperclass(env, context->class);
                while(super != 0) {
                    jclass tmp_cb;
                    *gptr++ = make_class_info(context, super);
                    tmp_cb = (*env)->GetSuperclass(env, super);
                    (*env)->DeleteLocalRef(env, super);
                    super = tmp_cb;
                }
                *gptr = 0;
            } else {
                context->superclass_info = 0;
            }

            (*env)->DeleteLocalRef(env, super);

    {- -------------------------------------------
  (1.1) veirfy 対象クラスの全てのフィールドに対し
        verify_field() を呼び出し, verification を行う.
        ---------------------------------------- -}

            /* Look at each method */
            for (i = JVM_GetClassFieldsCount(env, cb); --i >= 0;)
                verify_field(context, cb, i);

    {- -------------------------------------------
  (1.1) veirfy 対象クラスの全てのメソッドに対し
        verify_method() を呼び出し, verification を行う.
        ---------------------------------------- -}

            num_methods = JVM_GetClassMethodsCount(env, cb);
            read_all_code(context, cb, num_methods, &code_lengths, &code);
            for (i = num_methods - 1; i >= 0; --i)
                verify_method(context, cb, i, code_lengths[i], code[i]);
            free_all_code(context, num_methods, code);

    {- -------------------------------------------
  (1.1) verify 結果は成功(CC_OK)とする
        ---------------------------------------- -}

            result = CC_OK;

  {- -------------------------------------------
  (1) もし longjmp() で返ってきた場合は, 
      (エラーが起きているので)
      verify 結果として発生したエラーを設定
      ---------------------------------------- -}

        } else {
            result = context->err_code;
        }

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

        /* Cleanup */
        finalize_class_hash(context);

        while(context->allocated_memory)
            pop_and_free(context);

  {- -------------------------------------------
  (1) (デバッグ用の処理) (#ifdef DEBUG 時にのみ実行)
      ---------------------------------------- -}

    #ifdef DEBUG
        GlobalContext = 0;
    #endif

  {- -------------------------------------------
  (1) 確保したメモリを解放しておく.
      ---------------------------------------- -}

        if (context->exceptions)
            free(context->exceptions);

        if (context->constant_types)
            free(context->constant_types);

        if (context->superclasses)
            free(context->superclasses);

  {- -------------------------------------------
  (1) (デバッグ用の処理) (#ifdef DEBUG 時にのみ実行)
      ---------------------------------------- -}

    #ifdef DEBUG
        /* Make sure all global refs created in the verifier are freed */
        assert(context->n_globalrefs == 0);
    #endif

  {- -------------------------------------------
  (1) 確保したメモリを解放しておく.
      ---------------------------------------- -}

        CCdestroy(context);         /* destroy heap */

  {- -------------------------------------------
  (1) 結果をリターン
      ---------------------------------------- -}

        return result;
    }

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.