jdk/src/share/instrument/InvocationAdapter.c
/*
* 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.
*/
JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *tail, void * reserved) {
{- -------------------------------------------
(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.