Top


定義場所(file name)

jdk/src/share/instrument/InvocationAdapter.c

説明(description)

/*
 *  This will be called once for every -javaagent on the command line.
 *  Each call to Agent_OnLoad will create its own agent and agent data.
 *
 *  The argument tail string provided to Agent_OnLoad will be of form
 *  <jarfile>[=<options>]. The tail string is split into the jarfile and
 *  options components. The jarfile manifest is parsed and the value of the
 *  Premain-Class attribute will become the agent's premain class. The jar
 *  file is then added to the system class path, and if the Boot-Class-Path
 *  attribute is present then all relative URLs in the value are processed
 *  to create boot class path segments to append to the boot class path.
 */

名前(function name)

JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *tail, void * reserved) {

本体部(body)

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

        JPLISInitializationError initerror  = JPLIS_INIT_ERROR_NONE;
        jint                     result     = JNI_OK;
        JPLISAgent *             agent      = NULL;

  {- -------------------------------------------
  (1) createNewJPLISAgent() で JPLISAgent オブジェクトを生成する.
      ---------------------------------------- -}

        initerror = createNewJPLISAgent(vm, &agent);

  {- -------------------------------------------
  (1) もし生成に成功していれば, 以下の if ブロックの中で
      コマンドラインオプションのパース
      ---------------------------------------- -}

        if ( initerror == JPLIS_INIT_ERROR_NONE ) {

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

            int             oldLen, newLen;
            char *          jarfile;
            char *          options;
            jarAttribute*   attributes;
            char *          premainClass;
            char *          agentClass;
            char *          bootClassPath;

    {- -------------------------------------------
  (1.1) "<jarfile>[=options]" という形式のコマンドラインオプションを 
        jarfile 部分と option 部分にパースする.
        (失敗したら, この時点でリターン)
        ---------------------------------------- -}

            /*
             * Parse <jarfile>[=options] into jarfile and options
             */
            if (parseArgumentTail(tail, &jarfile, &options) != 0) {
                fprintf(stderr, "-javaagent: memory allocation failure.\n");
                return JNI_ERR;
            }

    {- -------------------------------------------
  (1.1) readAttributes() 及び getAttribute() で
        指定された jar file 中から "Premain-Class" 情報を取得する.

        (なお, 指定されたファイルが開けなかったり, JAR manifest が見つからなかったり,
         "Premain-Class" attribute が無かった場合は, 
         この時点でリターン)
        ---------------------------------------- -}

            /*
             * Agent_OnLoad is specified to provide the agent options
             * argument tail in modified UTF8. However for 1.5.0 this is
             * actually in the platform encoding - see 5049313.
             *
             * Open zip/jar file and parse archive. If can't be opened or
             * not a zip file return error. Also if Premain-Class attribute
             * isn't present we return an error.
             */
            attributes = readAttributes(jarfile);
            if (attributes == NULL) {
                fprintf(stderr, "Error opening zip file or JAR manifest missing : %s\n", jarfile);
                free(jarfile);
                if (options != NULL) free(options);
                return JNI_ERR;
            }

            premainClass = getAttribute(attributes, "Premain-Class");
            if (premainClass == NULL) {
                fprintf(stderr, "Failed to find Premain-Class manifest attribute in %s\n",
                    jarfile);
                free(jarfile);
                if (options != NULL) free(options);
                freeAttributes(attributes);
                return JNI_ERR;
            }

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

            /*
             * Add to the jarfile
             */
            appendClassPath(agent, jarfile);

    {- -------------------------------------------
  (1.1) 
        ---------------------------------------- -}

            /*
             * The value of the Premain-Class attribute becomes the agent
             * class name. The manifest is in UTF8 so need to convert to
             * modified UTF8 (see JNI spec).
             */
            oldLen = (int)strlen(premainClass);
            newLen = modifiedUtf8LengthOfUtf8(premainClass, oldLen);
            if (newLen == oldLen) {
                premainClass = strdup(premainClass);
            } else {
                char* str = (char*)malloc( newLen+1 );
                if (str != NULL) {
                    convertUtf8ToModifiedUtf8(premainClass, oldLen, str, newLen);
                }
                premainClass = str;
            }
            if (premainClass == NULL) {
                fprintf(stderr, "-javaagent: memory allocation failed\n");
                free(jarfile);
                if (options != NULL) free(options);
                freeAttributes(attributes);
                return JNI_ERR;
            }

    {- -------------------------------------------
  (1.1) 
        ---------------------------------------- -}

            /*
             * If the Boot-Class-Path attribute is specified then we process
             * each relative URL and add it to the bootclasspath.
             */
            bootClassPath = getAttribute(attributes, "Boot-Class-Path");
            if (bootClassPath != NULL) {
                appendBootClassPath(agent, jarfile, bootClassPath);
            }

    {- -------------------------------------------
  (1.1) 
        ---------------------------------------- -}

            /*
             * Convert JAR attributes into agent capabilities
             */
            convertCapabilityAtrributes(attributes, agent);

    {- -------------------------------------------
  (1.1) recordCommandLineData() を呼んで, agent 内に 
        "Premain-Class" 情報とオプション情報を格納する.
        ---------------------------------------- -}

            /*
             * Track (record) the agent class name and options data
             */
            initerror = recordCommandLineData(agent, premainClass, options);

    {- -------------------------------------------
  (1.1) 以上の作業で使用したメモリを解放する.
        ---------------------------------------- -}

            /*
             * Clean-up
             */
            free(jarfile);
            if (options != NULL) free(options);
            freeAttributes(attributes);
            free(premainClass);
        }

  {- -------------------------------------------
  (1) 処理が成功していれば JNI_OK をリターン.
      そうでない場合は (fprintf でトレース出力を出した後で) JNI_ERR をリターン.
      ---------------------------------------- -}

        switch (initerror) {
        case JPLIS_INIT_ERROR_NONE:
          result = JNI_OK;
          break;
        case JPLIS_INIT_ERROR_CANNOT_CREATE_NATIVE_AGENT:
          result = JNI_ERR;
          fprintf(stderr, "java.lang.instrument/-javaagent: cannot create native agent.\n");
          break;
        case JPLIS_INIT_ERROR_FAILURE:
          result = JNI_ERR;
          fprintf(stderr, "java.lang.instrument/-javaagent: initialization of native agent failed.\n");
          break;
        case JPLIS_INIT_ERROR_ALLOCATION_FAILURE:
          result = JNI_ERR;
          fprintf(stderr, "java.lang.instrument/-javaagent: allocation failure.\n");
          break;
        case JPLIS_INIT_ERROR_AGENT_CLASS_NOT_SPECIFIED:
          result = JNI_ERR;
          fprintf(stderr, "-javaagent: agent class not specified.\n");
          break;
        default:
          result = JNI_ERR;
          fprintf(stderr, "java.lang.instrument/-javaagent: unknown error\n");
          break;
        }
        return result;
    }

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