jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c
changeset 45004 ea3137042a61
parent 40818 9c2079cba606
--- a/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c	Mon Apr 24 13:43:34 2017 +0800
+++ b/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c	Thu May 04 07:26:55 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -106,7 +106,7 @@
  * convert them to JVM TI capabilities.
  */
 void
-convertCapabilityAtrributes(const jarAttribute* attributes, JPLISAgent* agent) {
+convertCapabilityAttributes(const jarAttribute* attributes, JPLISAgent* agent) {
     /* set redefineClasses capability */
     if (getBooleanAttribute(attributes, "Can-Redefine-Classes")) {
         addRedefineClassesCapability(agent);
@@ -229,7 +229,7 @@
         /*
          * Convert JAR attributes into agent capabilities
          */
-        convertCapabilityAtrributes(attributes, agent);
+        convertCapabilityAttributes(attributes, agent);
 
         /*
          * Track (record) the agent class name and options data
@@ -386,7 +386,7 @@
         /*
          * Convert JAR attributes into agent capabilities
          */
-        convertCapabilityAtrributes(attributes, agent);
+        convertCapabilityAttributes(attributes, agent);
 
         /*
          * Create the java.lang.instrument.Instrumentation instance
@@ -435,6 +435,109 @@
 DEF_Agent_OnUnload(JavaVM *vm) {
 }
 
+/**
+ * Invoked by the java launcher to load an agent in the main executable JAR.
+ * The Launcher-Agent-Class attribute in the main manifest of the JAR file
+ * is the agent class.
+ *
+ * Returns JNI_OK if the agent is loaded and initialized; JNI_ERR if this
+ * function fails, possibly with a pending exception.
+ */
+jint loadAgent(JNIEnv* env, jstring path) {
+    JavaVM* vm;
+    JPLISAgent* agent;
+    const char* jarfile = NULL;
+    jarAttribute* attributes = NULL;
+    char* agentClass = NULL;
+    char* bootClassPath;
+    int oldLen, newLen;
+    jint result = JNI_ERR;
+
+    if ((*env)->GetJavaVM(env, &vm) < 0) {
+        return JNI_ERR;
+    }
+
+    // create JPLISAgent with JVMTI environment
+    if (createNewJPLISAgent(vm, &agent) != JPLIS_INIT_ERROR_NONE) {
+        return JNI_ERR;
+    }
+
+    // get path to JAR file as UTF-8 string
+    jarfile = (*env)->GetStringUTFChars(env, path, NULL);
+    if (jarfile == NULL) {
+        return JNI_ERR;
+    }
+
+    // read the attributes in the main section of JAR manifest
+    attributes = readAttributes(jarfile);
+    if (attributes == NULL) {
+        goto releaseAndReturn;
+    }
+
+    // Launcher-Agent-Class is required
+    agentClass = getAttribute(attributes, "Launcher-Agent-Class");
+    if (agentClass == NULL) {
+        goto releaseAndReturn;
+    }
+
+    // The value of Launcher-Agent-Class is in UTF-8, convert it to modified UTF-8
+    oldLen = (int) strlen(agentClass);
+    newLen = modifiedUtf8LengthOfUtf8(agentClass, oldLen);
+    if (newLen == oldLen) {
+        agentClass = strdup(agentClass);
+    } else {
+        char* str = (char*) malloc(newLen + 1);
+        if (str != NULL) {
+            convertUtf8ToModifiedUtf8(agentClass, oldLen, str, newLen);
+        }
+        agentClass = str;
+    }
+    if (agentClass == NULL) {
+         jthrowable oome = createThrowable(env, "java/lang/OutOfMemoryError", NULL);
+         if (oome != NULL) (*env)->Throw(env, oome);
+         goto releaseAndReturn;
+    }
+
+    // Boot-Class-Path
+    bootClassPath = getAttribute(attributes, "Boot-Class-Path");
+    if (bootClassPath != NULL) {
+        appendBootClassPath(agent, jarfile, bootClassPath);
+    }
+
+    // Can-XXXX capabilities
+    convertCapabilityAttributes(attributes, agent);
+
+    // Create the java.lang.instrument.Instrumentation object
+    if (!createInstrumentationImpl(env, agent)) {
+        goto releaseAndReturn;
+    }
+
+    // Enable the ClassFileLoadHook
+    if (!setLivePhaseEventHandlers(agent)) {
+        goto releaseAndReturn;
+    }
+
+    // invoke the agentmain method
+    if (!startJavaAgent(agent, env, agentClass, "", agent->mAgentmainCaller)) {
+        goto releaseAndReturn;
+    }
+
+    // initialization complete
+    result = JNI_OK;
+
+    releaseAndReturn:
+        if (agentClass != NULL) {
+            free(agentClass);
+        }
+        if (attributes != NULL) {
+            freeAttributes(attributes);
+        }
+        if (jarfile != NULL) {
+            (*env)->ReleaseStringUTFChars(env, path, jarfile);
+        }
+
+    return result;
+}
 
 /*
  *  JVMTI callback support