src/java.instrument/share/native/libinstrument/JPLISAgent.c
changeset 47216 71c04702a3d5
parent 41360 241663e51880
child 47651 148b73047771
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 /*
       
    27  * Copyright 2003 Wily Technology, Inc.
       
    28  */
       
    29 
       
    30 #include    <jni.h>
       
    31 #include    <jvm.h>
       
    32 #include    <jvmti.h>
       
    33 #include    <stdlib.h>
       
    34 #include    <string.h>
       
    35 #include    "JPLISAgent.h"
       
    36 #include    "JPLISAssert.h"
       
    37 #include    "Utilities.h"
       
    38 #include    "Reentrancy.h"
       
    39 #include    "JavaExceptions.h"
       
    40 
       
    41 #include    "EncodingSupport.h"
       
    42 #include    "FileSystemSupport.h"    /* For MAXPATHLEN & uintptr_t */
       
    43 
       
    44 #include    "sun_instrument_InstrumentationImpl.h"
       
    45 
       
    46 /*
       
    47  *  The JPLISAgent manages the initialization all of the Java programming language Agents.
       
    48  *  It also supports the native method bridge between the JPLIS and the JVMTI.
       
    49  *  It maintains a single JVMTI Env that all JPL agents share.
       
    50  *  It parses command line requests and creates individual Java agents.
       
    51  */
       
    52 
       
    53 
       
    54 /*
       
    55  *  private prototypes
       
    56  */
       
    57 
       
    58 /* Allocates an unformatted JPLIS agent data structure. Returns NULL if allocation fails. */
       
    59 JPLISAgent *
       
    60 allocateJPLISAgent(jvmtiEnv *       jvmtiEnv);
       
    61 
       
    62 /* Initializes an already-allocated JPLIS agent data structure. */
       
    63 JPLISInitializationError
       
    64 initializeJPLISAgent(   JPLISAgent *    agent,
       
    65                         JavaVM *        vm,
       
    66                         jvmtiEnv *      jvmtienv);
       
    67 /* De-allocates a JPLIS agent data structure. Only used in partial-failure cases at startup;
       
    68  * in normal usage the JPLIS agent lives forever
       
    69  */
       
    70 void
       
    71 deallocateJPLISAgent(   jvmtiEnv *      jvmtienv,
       
    72                         JPLISAgent *    agent);
       
    73 
       
    74 /* Does one-time work to interrogate the JVM about capabilities and cache the answers. */
       
    75 void
       
    76 checkCapabilities(JPLISAgent * agent);
       
    77 
       
    78 /* Takes the elements of the command string (agent class name and options string) and
       
    79  * create java strings for them.
       
    80  * Returns true if a classname was found. Makes no promises beyond the textual; says nothing about whether
       
    81  * the class exists or can be loaded.
       
    82  * If return value is true, sets outputClassname to a non-NULL local JNI reference.
       
    83  * If return value is true, sets outputOptionsString either to NULL or to a non-NULL local JNI reference.
       
    84  * If return value is false, neither output parameter is set.
       
    85  */
       
    86 jboolean
       
    87 commandStringIntoJavaStrings(  JNIEnv *        jnienv,
       
    88                                const char *    classname,
       
    89                                const char *    optionsString,
       
    90                                jstring *       outputClassname,
       
    91                                jstring *       outputOptionsString);
       
    92 
       
    93 /* Start one Java agent from the supplied parameters.
       
    94  * Most of the logic lives in a helper function that lives over in Java code--
       
    95  * we pass parameters out to Java and use our own Java helper to actually
       
    96  * load the agent and call the premain.
       
    97  * Returns true if the Java agent class is loaded and the premain/agentmain method completes
       
    98  * with no exceptions, false otherwise.
       
    99  */
       
   100 jboolean
       
   101 invokeJavaAgentMainMethod( JNIEnv *    jnienv,
       
   102                            jobject     instrumentationImpl,
       
   103                            jmethodID   agentMainMethod,
       
   104                            jstring     className,
       
   105                            jstring     optionsString);
       
   106 
       
   107 /* Once we have loaded the Java agent and called the premain,
       
   108  * we can release the copies we have been keeping of the command line
       
   109  * data (agent class name and option strings).
       
   110  */
       
   111 void
       
   112 deallocateCommandLineData(JPLISAgent * agent);
       
   113 
       
   114 /*
       
   115  *  Common support for various class list fetchers.
       
   116  */
       
   117 typedef jvmtiError (*ClassListFetcher)
       
   118     (   jvmtiEnv *  jvmtiEnv,
       
   119         jobject     classLoader,
       
   120         jint *      classCount,
       
   121         jclass **   classes);
       
   122 
       
   123 /* Fetcher that ignores the class loader parameter, and uses the JVMTI to get a list of all classes.
       
   124  * Returns a jvmtiError according to the underlying JVMTI service.
       
   125  */
       
   126 jvmtiError
       
   127 getAllLoadedClassesClassListFetcher(    jvmtiEnv *  jvmtiEnv,
       
   128                                         jobject     classLoader,
       
   129                                         jint *      classCount,
       
   130                                         jclass **   classes);
       
   131 
       
   132 /* Fetcher that uses the class loader parameter, and uses the JVMTI to get a list of all classes
       
   133  * for which the supplied loader is the initiating loader.
       
   134  * Returns a jvmtiError according to the underlying JVMTI service.
       
   135  */
       
   136 jvmtiError
       
   137 getInitiatedClassesClassListFetcher(    jvmtiEnv *  jvmtiEnv,
       
   138                                         jobject     classLoader,
       
   139                                         jint *      classCount,
       
   140                                         jclass **   classes);
       
   141 
       
   142 /*
       
   143  * Common guts for two native methods, which are the same except for the policy for fetching
       
   144  * the list of classes.
       
   145  * Either returns a local JNI reference to an array of references to java.lang.Class.
       
   146  * Can throw, if it does will alter the JNIEnv with an outstanding exception.
       
   147  */
       
   148 jobjectArray
       
   149 commonGetClassList( JNIEnv *            jnienv,
       
   150                     JPLISAgent *        agent,
       
   151                     jobject             classLoader,
       
   152                     ClassListFetcher    fetcher);
       
   153 
       
   154 
       
   155 /*
       
   156  *  Misc. utilities.
       
   157  */
       
   158 
       
   159 /* Checked exception mapper used by the redefine classes implementation.
       
   160  * Allows ClassNotFoundException or UnmodifiableClassException; maps others
       
   161  * to InternalError. Can return NULL in an error case.
       
   162  */
       
   163 jthrowable
       
   164 redefineClassMapper(    JNIEnv *    jnienv,
       
   165                         jthrowable  throwableToMap);
       
   166 
       
   167 /* Turns a buffer of jclass * into a Java array whose elements are java.lang.Class.
       
   168  * Can throw, if it does will alter the JNIEnv with an outstanding exception.
       
   169  */
       
   170 jobjectArray
       
   171 getObjectArrayFromClasses(JNIEnv* jnienv, jclass* classes, jint classCount);
       
   172 
       
   173 
       
   174 JPLISEnvironment *
       
   175 getJPLISEnvironment(jvmtiEnv * jvmtienv) {
       
   176     JPLISEnvironment * environment  = NULL;
       
   177     jvmtiError         jvmtierror   = JVMTI_ERROR_NONE;
       
   178 
       
   179     jvmtierror = (*jvmtienv)->GetEnvironmentLocalStorage(
       
   180                                             jvmtienv,
       
   181                                             (void**)&environment);
       
   182     /* can be called from any phase */
       
   183     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
   184 
       
   185     if (jvmtierror == JVMTI_ERROR_NONE) {
       
   186         jplis_assert(environment != NULL);
       
   187         jplis_assert(environment->mJVMTIEnv == jvmtienv);
       
   188     } else {
       
   189         environment = NULL;
       
   190     }
       
   191     return environment;
       
   192 }
       
   193 
       
   194 /*
       
   195  *  OnLoad processing code.
       
   196  */
       
   197 
       
   198 /*
       
   199  *  Creates a new JPLISAgent.
       
   200  *  Returns error if the agent cannot be created and initialized.
       
   201  *  The JPLISAgent* pointed to by agent_ptr is set to the new broker,
       
   202  *  or NULL if an error has occurred.
       
   203  */
       
   204 JPLISInitializationError
       
   205 createNewJPLISAgent(JavaVM * vm, JPLISAgent **agent_ptr) {
       
   206     JPLISInitializationError initerror       = JPLIS_INIT_ERROR_NONE;
       
   207     jvmtiEnv *               jvmtienv        = NULL;
       
   208     jint                     jnierror        = JNI_OK;
       
   209 
       
   210     *agent_ptr = NULL;
       
   211     jnierror = (*vm)->GetEnv(  vm,
       
   212                                (void **) &jvmtienv,
       
   213                                JVMTI_VERSION_1_1);
       
   214     if ( jnierror != JNI_OK ) {
       
   215         initerror = JPLIS_INIT_ERROR_CANNOT_CREATE_NATIVE_AGENT;
       
   216     } else {
       
   217         JPLISAgent * agent = allocateJPLISAgent(jvmtienv);
       
   218         if ( agent == NULL ) {
       
   219             initerror = JPLIS_INIT_ERROR_ALLOCATION_FAILURE;
       
   220         } else {
       
   221             initerror = initializeJPLISAgent(  agent,
       
   222                                                vm,
       
   223                                                jvmtienv);
       
   224             if ( initerror == JPLIS_INIT_ERROR_NONE ) {
       
   225                 *agent_ptr = agent;
       
   226             } else {
       
   227                 deallocateJPLISAgent(jvmtienv, agent);
       
   228             }
       
   229         }
       
   230 
       
   231         /* don't leak envs */
       
   232         if ( initerror != JPLIS_INIT_ERROR_NONE ) {
       
   233             jvmtiError jvmtierror = (*jvmtienv)->DisposeEnvironment(jvmtienv);
       
   234             /* can be called from any phase */
       
   235             jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
   236         }
       
   237     }
       
   238 
       
   239     return initerror;
       
   240 }
       
   241 
       
   242 /*
       
   243  *  Allocates a JPLISAgent. Returns NULL if it cannot be allocated
       
   244  */
       
   245 JPLISAgent *
       
   246 allocateJPLISAgent(jvmtiEnv * jvmtienv) {
       
   247   return (JPLISAgent *) allocate( jvmtienv,
       
   248                                     sizeof(JPLISAgent));
       
   249 }
       
   250 
       
   251 JPLISInitializationError
       
   252 initializeJPLISAgent(   JPLISAgent *    agent,
       
   253                         JavaVM *        vm,
       
   254                         jvmtiEnv *      jvmtienv) {
       
   255     jvmtiError      jvmtierror = JVMTI_ERROR_NONE;
       
   256     jvmtiPhase      phase;
       
   257 
       
   258     agent->mJVM                                      = vm;
       
   259     agent->mNormalEnvironment.mJVMTIEnv              = jvmtienv;
       
   260     agent->mNormalEnvironment.mAgent                 = agent;
       
   261     agent->mNormalEnvironment.mIsRetransformer       = JNI_FALSE;
       
   262     agent->mRetransformEnvironment.mJVMTIEnv         = NULL;        /* NULL until needed */
       
   263     agent->mRetransformEnvironment.mAgent            = agent;
       
   264     agent->mRetransformEnvironment.mIsRetransformer  = JNI_FALSE;   /* JNI_FALSE until mJVMTIEnv is set */
       
   265     agent->mAgentmainCaller                          = NULL;
       
   266     agent->mInstrumentationImpl                      = NULL;
       
   267     agent->mPremainCaller                            = NULL;
       
   268     agent->mTransform                                = NULL;
       
   269     agent->mRedefineAvailable                        = JNI_FALSE;   /* assume no for now */
       
   270     agent->mRedefineAdded                            = JNI_FALSE;
       
   271     agent->mNativeMethodPrefixAvailable              = JNI_FALSE;   /* assume no for now */
       
   272     agent->mNativeMethodPrefixAdded                  = JNI_FALSE;
       
   273     agent->mAgentClassName                           = NULL;
       
   274     agent->mOptionsString                            = NULL;
       
   275     agent->mJarfile                                  = NULL;
       
   276 
       
   277     /* make sure we can recover either handle in either direction.
       
   278      * the agent has a ref to the jvmti; make it mutual
       
   279      */
       
   280     jvmtierror = (*jvmtienv)->SetEnvironmentLocalStorage(
       
   281                                             jvmtienv,
       
   282                                             &(agent->mNormalEnvironment));
       
   283     /* can be called from any phase */
       
   284     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
   285 
       
   286     /* check what capabilities are available */
       
   287     checkCapabilities(agent);
       
   288 
       
   289     /* check phase - if live phase then we don't need the VMInit event */
       
   290     jvmtierror = (*jvmtienv)->GetPhase(jvmtienv, &phase);
       
   291     /* can be called from any phase */
       
   292     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
   293     if (phase == JVMTI_PHASE_LIVE) {
       
   294         return JPLIS_INIT_ERROR_NONE;
       
   295     }
       
   296 
       
   297     if (phase != JVMTI_PHASE_ONLOAD) {
       
   298         /* called too early or called too late; either way bail out */
       
   299         return JPLIS_INIT_ERROR_FAILURE;
       
   300     }
       
   301 
       
   302     /* now turn on the VMInit event */
       
   303     if ( jvmtierror == JVMTI_ERROR_NONE ) {
       
   304         jvmtiEventCallbacks callbacks;
       
   305         memset(&callbacks, 0, sizeof(callbacks));
       
   306         callbacks.VMInit = &eventHandlerVMInit;
       
   307 
       
   308         jvmtierror = (*jvmtienv)->SetEventCallbacks( jvmtienv,
       
   309                                                      &callbacks,
       
   310                                                      sizeof(callbacks));
       
   311         check_phase_ret_blob(jvmtierror, JPLIS_INIT_ERROR_FAILURE);
       
   312         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
   313     }
       
   314 
       
   315     if ( jvmtierror == JVMTI_ERROR_NONE ) {
       
   316         jvmtierror = (*jvmtienv)->SetEventNotificationMode(
       
   317                                                 jvmtienv,
       
   318                                                 JVMTI_ENABLE,
       
   319                                                 JVMTI_EVENT_VM_INIT,
       
   320                                                 NULL /* all threads */);
       
   321         check_phase_ret_blob(jvmtierror, JPLIS_INIT_ERROR_FAILURE);
       
   322         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
   323     }
       
   324 
       
   325     return (jvmtierror == JVMTI_ERROR_NONE)? JPLIS_INIT_ERROR_NONE : JPLIS_INIT_ERROR_FAILURE;
       
   326 }
       
   327 
       
   328 void
       
   329 deallocateJPLISAgent(jvmtiEnv * jvmtienv, JPLISAgent * agent) {
       
   330     deallocate(jvmtienv, agent);
       
   331 }
       
   332 
       
   333 
       
   334 JPLISInitializationError
       
   335 recordCommandLineData(  JPLISAgent *    agent,
       
   336                         const char *    agentClassName,
       
   337                         const char *    optionsString ) {
       
   338     JPLISInitializationError    initerror   = JPLIS_INIT_ERROR_NONE;
       
   339     char *      ourCopyOfAgentClassName     = NULL;
       
   340     char *      ourCopyOfOptionsString      = NULL;
       
   341 
       
   342     /* if no actual params, bail out now */
       
   343     if ((agentClassName == NULL) || (*agentClassName == 0)) {
       
   344         initerror = JPLIS_INIT_ERROR_AGENT_CLASS_NOT_SPECIFIED;
       
   345     } else {
       
   346         ourCopyOfAgentClassName = allocate(jvmti(agent), strlen(agentClassName)+1);
       
   347         if (ourCopyOfAgentClassName == NULL) {
       
   348             initerror = JPLIS_INIT_ERROR_ALLOCATION_FAILURE;
       
   349         } else {
       
   350             if (optionsString != NULL) {
       
   351                 ourCopyOfOptionsString = allocate(jvmti(agent), strlen(optionsString)+1);
       
   352                 if (ourCopyOfOptionsString == NULL) {
       
   353                     deallocate(jvmti(agent), ourCopyOfAgentClassName);
       
   354                     initerror = JPLIS_INIT_ERROR_ALLOCATION_FAILURE;
       
   355                 }
       
   356             }
       
   357         }
       
   358     }
       
   359 
       
   360     if (initerror == JPLIS_INIT_ERROR_NONE) {
       
   361         strcpy(ourCopyOfAgentClassName, agentClassName);
       
   362         if (optionsString != NULL) {
       
   363             strcpy(ourCopyOfOptionsString, optionsString);
       
   364         }
       
   365         agent->mAgentClassName = ourCopyOfAgentClassName;
       
   366         agent->mOptionsString = ourCopyOfOptionsString;
       
   367     }
       
   368 
       
   369     return initerror;
       
   370 }
       
   371 
       
   372 /*
       
   373  *  VMInit processing code.
       
   374  */
       
   375 
       
   376 
       
   377 /*
       
   378  * If this call fails, the JVM launch will ultimately be aborted,
       
   379  * so we don't have to be super-careful to clean up in partial failure
       
   380  * cases.
       
   381  */
       
   382 jboolean
       
   383 processJavaStart(   JPLISAgent *    agent,
       
   384                     JNIEnv *        jnienv) {
       
   385     jboolean    result;
       
   386 
       
   387     /*
       
   388      *  OK, Java is up now. We can start everything that needs Java.
       
   389      */
       
   390 
       
   391     /*
       
   392      *  First make our emergency fallback InternalError throwable.
       
   393      */
       
   394     result = initializeFallbackError(jnienv);
       
   395     jplis_assert(result);
       
   396 
       
   397     /*
       
   398      *  Now make the InstrumentationImpl instance.
       
   399      */
       
   400     if ( result ) {
       
   401         result = createInstrumentationImpl(jnienv, agent);
       
   402         jplis_assert(result);
       
   403     }
       
   404 
       
   405 
       
   406     /*
       
   407      *  Then turn off the VMInit handler and turn on the ClassFileLoadHook.
       
   408      *  This way it is on before anyone registers a transformer.
       
   409      */
       
   410     if ( result ) {
       
   411         result = setLivePhaseEventHandlers(agent);
       
   412         jplis_assert(result);
       
   413     }
       
   414 
       
   415     /*
       
   416      *  Load the Java agent, and call the premain.
       
   417      */
       
   418     if ( result ) {
       
   419         result = startJavaAgent(agent, jnienv,
       
   420                                 agent->mAgentClassName, agent->mOptionsString,
       
   421                                 agent->mPremainCaller);
       
   422     }
       
   423 
       
   424     /*
       
   425      * Finally surrender all of the tracking data that we don't need any more.
       
   426      * If something is wrong, skip it, we will be aborting the JVM anyway.
       
   427      */
       
   428     if ( result ) {
       
   429         deallocateCommandLineData(agent);
       
   430     }
       
   431 
       
   432     return result;
       
   433 }
       
   434 
       
   435 jboolean
       
   436 startJavaAgent( JPLISAgent *    agent,
       
   437                 JNIEnv *        jnienv,
       
   438                 const char *    classname,
       
   439                 const char *    optionsString,
       
   440                 jmethodID       agentMainMethod) {
       
   441     jboolean    success = JNI_FALSE;
       
   442     jstring classNameObject = NULL;
       
   443     jstring optionsStringObject = NULL;
       
   444 
       
   445     success = commandStringIntoJavaStrings(    jnienv,
       
   446                                                classname,
       
   447                                                optionsString,
       
   448                                                &classNameObject,
       
   449                                                &optionsStringObject);
       
   450 
       
   451     if (success) {
       
   452         success = invokeJavaAgentMainMethod(   jnienv,
       
   453                                                agent->mInstrumentationImpl,
       
   454                                                agentMainMethod,
       
   455                                                classNameObject,
       
   456                                                optionsStringObject);
       
   457     }
       
   458 
       
   459     return success;
       
   460 }
       
   461 
       
   462 void
       
   463 deallocateCommandLineData( JPLISAgent * agent) {
       
   464     deallocate(jvmti(agent), (void*)agent->mAgentClassName);
       
   465     deallocate(jvmti(agent), (void*)agent->mOptionsString);
       
   466 
       
   467     /* zero things out so it is easier to see what is going on */
       
   468     agent->mAgentClassName = NULL;
       
   469     agent->mOptionsString = NULL;
       
   470 }
       
   471 
       
   472 /*
       
   473  * Create the java.lang.instrument.Instrumentation instance
       
   474  * and access information for it (method IDs, etc)
       
   475  */
       
   476 jboolean
       
   477 createInstrumentationImpl( JNIEnv *        jnienv,
       
   478                            JPLISAgent *    agent) {
       
   479     jclass      implClass               = NULL;
       
   480     jboolean    errorOutstanding        = JNI_FALSE;
       
   481     jobject     resultImpl              = NULL;
       
   482     jmethodID   premainCallerMethodID   = NULL;
       
   483     jmethodID   agentmainCallerMethodID = NULL;
       
   484     jmethodID   transformMethodID       = NULL;
       
   485     jmethodID   constructorID           = NULL;
       
   486     jobject     localReference          = NULL;
       
   487 
       
   488     /* First find the class of our implementation */
       
   489     implClass = (*jnienv)->FindClass(   jnienv,
       
   490                                         JPLIS_INSTRUMENTIMPL_CLASSNAME);
       
   491     errorOutstanding = checkForAndClearThrowable(jnienv);
       
   492     errorOutstanding = errorOutstanding || (implClass == NULL);
       
   493     jplis_assert_msg(!errorOutstanding, "find class on InstrumentationImpl failed");
       
   494 
       
   495     if ( !errorOutstanding ) {
       
   496         constructorID = (*jnienv)->GetMethodID( jnienv,
       
   497                                                 implClass,
       
   498                                                 JPLIS_INSTRUMENTIMPL_CONSTRUCTOR_METHODNAME,
       
   499                                                 JPLIS_INSTRUMENTIMPL_CONSTRUCTOR_METHODSIGNATURE);
       
   500         errorOutstanding = checkForAndClearThrowable(jnienv);
       
   501         errorOutstanding = errorOutstanding || (constructorID == NULL);
       
   502         jplis_assert_msg(!errorOutstanding, "find constructor on InstrumentationImpl failed");
       
   503         }
       
   504 
       
   505     if ( !errorOutstanding ) {
       
   506         jlong   peerReferenceAsScalar = (jlong)(intptr_t) agent;
       
   507         localReference = (*jnienv)->NewObject(  jnienv,
       
   508                                                 implClass,
       
   509                                                 constructorID,
       
   510                                                 peerReferenceAsScalar,
       
   511                                                 agent->mRedefineAdded,
       
   512                                                 agent->mNativeMethodPrefixAdded);
       
   513         errorOutstanding = checkForAndClearThrowable(jnienv);
       
   514         errorOutstanding = errorOutstanding || (localReference == NULL);
       
   515         jplis_assert_msg(!errorOutstanding, "call constructor on InstrumentationImpl failed");
       
   516     }
       
   517 
       
   518     if ( !errorOutstanding ) {
       
   519         resultImpl = (*jnienv)->NewGlobalRef(jnienv, localReference);
       
   520         errorOutstanding = checkForAndClearThrowable(jnienv);
       
   521         jplis_assert_msg(!errorOutstanding, "copy local ref to global ref");
       
   522     }
       
   523 
       
   524     /* Now look up the method ID for the pre-main caller (we will need this more than once) */
       
   525     if ( !errorOutstanding ) {
       
   526         premainCallerMethodID = (*jnienv)->GetMethodID( jnienv,
       
   527                                                         implClass,
       
   528                                                         JPLIS_INSTRUMENTIMPL_PREMAININVOKER_METHODNAME,
       
   529                                                         JPLIS_INSTRUMENTIMPL_PREMAININVOKER_METHODSIGNATURE);
       
   530         errorOutstanding = checkForAndClearThrowable(jnienv);
       
   531         errorOutstanding = errorOutstanding || (premainCallerMethodID == NULL);
       
   532         jplis_assert_msg(!errorOutstanding, "can't find premain invoker methodID");
       
   533     }
       
   534 
       
   535     /* Now look up the method ID for the agent-main caller */
       
   536     if ( !errorOutstanding ) {
       
   537         agentmainCallerMethodID = (*jnienv)->GetMethodID( jnienv,
       
   538                                                           implClass,
       
   539                                                           JPLIS_INSTRUMENTIMPL_AGENTMAININVOKER_METHODNAME,
       
   540                                                           JPLIS_INSTRUMENTIMPL_AGENTMAININVOKER_METHODSIGNATURE);
       
   541         errorOutstanding = checkForAndClearThrowable(jnienv);
       
   542         errorOutstanding = errorOutstanding || (agentmainCallerMethodID == NULL);
       
   543         jplis_assert_msg(!errorOutstanding, "can't find agentmain invoker methodID");
       
   544     }
       
   545 
       
   546     /* Now look up the method ID for the transform method (we will need this constantly) */
       
   547     if ( !errorOutstanding ) {
       
   548         transformMethodID = (*jnienv)->GetMethodID( jnienv,
       
   549                                                     implClass,
       
   550                                                     JPLIS_INSTRUMENTIMPL_TRANSFORM_METHODNAME,
       
   551                                                     JPLIS_INSTRUMENTIMPL_TRANSFORM_METHODSIGNATURE);
       
   552         errorOutstanding = checkForAndClearThrowable(jnienv);
       
   553         errorOutstanding = errorOutstanding || (transformMethodID == NULL);
       
   554         jplis_assert_msg(!errorOutstanding, "can't find transform methodID");
       
   555     }
       
   556 
       
   557     if ( !errorOutstanding ) {
       
   558         agent->mInstrumentationImpl = resultImpl;
       
   559         agent->mPremainCaller       = premainCallerMethodID;
       
   560         agent->mAgentmainCaller     = agentmainCallerMethodID;
       
   561         agent->mTransform           = transformMethodID;
       
   562     }
       
   563 
       
   564     return !errorOutstanding;
       
   565 }
       
   566 
       
   567 jboolean
       
   568 commandStringIntoJavaStrings(  JNIEnv *        jnienv,
       
   569                                const char *    classname,
       
   570                                const char *    optionsString,
       
   571                                jstring *       outputClassname,
       
   572                                jstring *       outputOptionsString) {
       
   573     jstring     classnameJavaString     = NULL;
       
   574     jstring     optionsJavaString       = NULL;
       
   575     jboolean    errorOutstanding        = JNI_TRUE;
       
   576 
       
   577     classnameJavaString = (*jnienv)->NewStringUTF(jnienv, classname);
       
   578     errorOutstanding = checkForAndClearThrowable(jnienv);
       
   579     jplis_assert_msg(!errorOutstanding, "can't create class name java string");
       
   580 
       
   581     if ( !errorOutstanding ) {
       
   582         if ( optionsString != NULL) {
       
   583             optionsJavaString = (*jnienv)->NewStringUTF(jnienv, optionsString);
       
   584             errorOutstanding = checkForAndClearThrowable(jnienv);
       
   585             jplis_assert_msg(!errorOutstanding, "can't create options java string");
       
   586         }
       
   587 
       
   588         if ( !errorOutstanding ) {
       
   589             *outputClassname        = classnameJavaString;
       
   590             *outputOptionsString    = optionsJavaString;
       
   591         }
       
   592     }
       
   593 
       
   594     return !errorOutstanding;
       
   595 }
       
   596 
       
   597 
       
   598 jboolean
       
   599 invokeJavaAgentMainMethod( JNIEnv *    jnienv,
       
   600                            jobject     instrumentationImpl,
       
   601                            jmethodID   mainCallingMethod,
       
   602                            jstring     className,
       
   603                            jstring     optionsString) {
       
   604     jboolean errorOutstanding = JNI_FALSE;
       
   605 
       
   606     jplis_assert(mainCallingMethod != NULL);
       
   607     if ( mainCallingMethod != NULL ) {
       
   608         (*jnienv)->CallVoidMethod(  jnienv,
       
   609                                     instrumentationImpl,
       
   610                                     mainCallingMethod,
       
   611                                     className,
       
   612                                     optionsString);
       
   613         errorOutstanding = checkForThrowable(jnienv);
       
   614         if ( errorOutstanding ) {
       
   615             logThrowable(jnienv);
       
   616         }
       
   617         checkForAndClearThrowable(jnienv);
       
   618     }
       
   619     return !errorOutstanding;
       
   620 }
       
   621 
       
   622 jboolean
       
   623 setLivePhaseEventHandlers(  JPLISAgent * agent) {
       
   624     jvmtiEventCallbacks callbacks;
       
   625     jvmtiEnv *          jvmtienv = jvmti(agent);
       
   626     jvmtiError          jvmtierror;
       
   627 
       
   628     /* first swap out the handlers (switch from the VMInit handler, which we do not need,
       
   629      * to the ClassFileLoadHook handler, which is what the agents need from now on)
       
   630      */
       
   631     memset(&callbacks, 0, sizeof(callbacks));
       
   632     callbacks.ClassFileLoadHook = &eventHandlerClassFileLoadHook;
       
   633 
       
   634     jvmtierror = (*jvmtienv)->SetEventCallbacks( jvmtienv,
       
   635                                                  &callbacks,
       
   636                                                  sizeof(callbacks));
       
   637     check_phase_ret_false(jvmtierror);
       
   638     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
   639 
       
   640 
       
   641     if ( jvmtierror == JVMTI_ERROR_NONE ) {
       
   642         /* turn off VMInit */
       
   643         jvmtierror = (*jvmtienv)->SetEventNotificationMode(
       
   644                                                     jvmtienv,
       
   645                                                     JVMTI_DISABLE,
       
   646                                                     JVMTI_EVENT_VM_INIT,
       
   647                                                     NULL /* all threads */);
       
   648         check_phase_ret_false(jvmtierror);
       
   649         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
   650     }
       
   651 
       
   652     if ( jvmtierror == JVMTI_ERROR_NONE ) {
       
   653         /* turn on ClassFileLoadHook */
       
   654         jvmtierror = (*jvmtienv)->SetEventNotificationMode(
       
   655                                                     jvmtienv,
       
   656                                                     JVMTI_ENABLE,
       
   657                                                     JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
       
   658                                                     NULL /* all threads */);
       
   659         check_phase_ret_false(jvmtierror);
       
   660         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
   661     }
       
   662 
       
   663     return (jvmtierror == JVMTI_ERROR_NONE);
       
   664 }
       
   665 
       
   666 /**
       
   667  *  Check if the can_redefine_classes capability is available.
       
   668  */
       
   669 void
       
   670 checkCapabilities(JPLISAgent * agent) {
       
   671     jvmtiEnv *          jvmtienv = jvmti(agent);
       
   672     jvmtiCapabilities   potentialCapabilities;
       
   673     jvmtiError          jvmtierror;
       
   674 
       
   675     memset(&potentialCapabilities, 0, sizeof(potentialCapabilities));
       
   676 
       
   677     jvmtierror = (*jvmtienv)->GetPotentialCapabilities(jvmtienv, &potentialCapabilities);
       
   678     check_phase_ret(jvmtierror);
       
   679     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
   680 
       
   681     if ( jvmtierror == JVMTI_ERROR_NONE ) {
       
   682         if ( potentialCapabilities.can_redefine_classes == 1 ) {
       
   683             agent->mRedefineAvailable = JNI_TRUE;
       
   684         }
       
   685         if ( potentialCapabilities.can_set_native_method_prefix == 1 ) {
       
   686             agent->mNativeMethodPrefixAvailable = JNI_TRUE;
       
   687         }
       
   688     }
       
   689 }
       
   690 
       
   691 /**
       
   692  * Enable native method prefix in one JVM TI environment
       
   693  */
       
   694 void
       
   695 enableNativeMethodPrefixCapability(jvmtiEnv * jvmtienv) {
       
   696     jvmtiCapabilities   desiredCapabilities;
       
   697     jvmtiError          jvmtierror;
       
   698 
       
   699         jvmtierror = (*jvmtienv)->GetCapabilities(jvmtienv, &desiredCapabilities);
       
   700         /* can be called from any phase */
       
   701         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
   702         desiredCapabilities.can_set_native_method_prefix = 1;
       
   703         jvmtierror = (*jvmtienv)->AddCapabilities(jvmtienv, &desiredCapabilities);
       
   704         check_phase_ret(jvmtierror);
       
   705         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
   706 }
       
   707 
       
   708 
       
   709 /**
       
   710  * Add the can_set_native_method_prefix capability
       
   711  */
       
   712 void
       
   713 addNativeMethodPrefixCapability(JPLISAgent * agent) {
       
   714     if (agent->mNativeMethodPrefixAvailable && !agent->mNativeMethodPrefixAdded) {
       
   715         jvmtiEnv * jvmtienv = agent->mNormalEnvironment.mJVMTIEnv;
       
   716         enableNativeMethodPrefixCapability(jvmtienv);
       
   717 
       
   718         jvmtienv = agent->mRetransformEnvironment.mJVMTIEnv;
       
   719         if (jvmtienv != NULL) {
       
   720             enableNativeMethodPrefixCapability(jvmtienv);
       
   721         }
       
   722         agent->mNativeMethodPrefixAdded = JNI_TRUE;
       
   723     }
       
   724 }
       
   725 
       
   726 /**
       
   727  * Add the can_maintain_original_method_order capability (for testing)
       
   728  */
       
   729 void
       
   730 addOriginalMethodOrderCapability(JPLISAgent * agent) {
       
   731     jvmtiEnv *          jvmtienv = jvmti(agent);
       
   732     jvmtiCapabilities   desiredCapabilities;
       
   733     jvmtiError          jvmtierror;
       
   734 
       
   735     jvmtierror = (*jvmtienv)->GetCapabilities(jvmtienv, &desiredCapabilities);
       
   736     /* can be called from any phase */
       
   737     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
   738     desiredCapabilities.can_maintain_original_method_order = 1;
       
   739     jvmtierror = (*jvmtienv)->AddCapabilities(jvmtienv, &desiredCapabilities);
       
   740     check_phase_ret(jvmtierror);
       
   741     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
   742 }
       
   743 
       
   744 /**
       
   745  * Add the can_redefine_classes capability
       
   746  */
       
   747 void
       
   748 addRedefineClassesCapability(JPLISAgent * agent) {
       
   749     jvmtiEnv *          jvmtienv = jvmti(agent);
       
   750     jvmtiCapabilities   desiredCapabilities;
       
   751     jvmtiError          jvmtierror;
       
   752 
       
   753     if (agent->mRedefineAvailable && !agent->mRedefineAdded) {
       
   754         jvmtierror = (*jvmtienv)->GetCapabilities(jvmtienv, &desiredCapabilities);
       
   755         /* can be called from any phase */
       
   756         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
   757         desiredCapabilities.can_redefine_classes = 1;
       
   758         jvmtierror = (*jvmtienv)->AddCapabilities(jvmtienv, &desiredCapabilities);
       
   759         check_phase_ret(jvmtierror);
       
   760 
       
   761         /*
       
   762          * With mixed premain/agentmain agents then it's possible that the
       
   763          * capability was potentially available in the onload phase but
       
   764          * subsequently unavailable in the live phase.
       
   765          */
       
   766         jplis_assert(jvmtierror == JVMTI_ERROR_NONE ||
       
   767                      jvmtierror == JVMTI_ERROR_NOT_AVAILABLE);
       
   768         if (jvmtierror == JVMTI_ERROR_NONE) {
       
   769             agent->mRedefineAdded = JNI_TRUE;
       
   770         }
       
   771     }
       
   772 }
       
   773 
       
   774 static jobject
       
   775 getModuleObject(jvmtiEnv*               jvmti,
       
   776                 jobject                 loaderObject,
       
   777                 const char*             cname) {
       
   778     jvmtiError err = JVMTI_ERROR_NONE;
       
   779     jobject moduleObject = NULL;
       
   780 
       
   781     /* find last slash in the class name */
       
   782     char* last_slash = (cname == NULL) ? NULL : strrchr(cname, '/');
       
   783     int len = (last_slash == NULL) ? 0 : (int)(last_slash - cname);
       
   784     char* pkg_name_buf = (char*)malloc(len + 1);
       
   785 
       
   786     jplis_assert_msg(pkg_name_buf != NULL, "OOM error in native tmp buffer allocation");
       
   787     if (last_slash != NULL) {
       
   788         strncpy(pkg_name_buf, cname, len);
       
   789     }
       
   790     pkg_name_buf[len] = '\0';
       
   791 
       
   792     err = (*jvmti)->GetNamedModule(jvmti, loaderObject, pkg_name_buf, &moduleObject);
       
   793     free((void*)pkg_name_buf);
       
   794     check_phase_ret_blob(err, NULL);
       
   795     jplis_assert_msg(err == JVMTI_ERROR_NONE, "error in the JVMTI GetNamedModule");
       
   796 
       
   797     return moduleObject;
       
   798 }
       
   799 
       
   800 /*
       
   801  *  Support for the JVMTI callbacks
       
   802  */
       
   803 
       
   804 void
       
   805 transformClassFile(             JPLISAgent *            agent,
       
   806                                 JNIEnv *                jnienv,
       
   807                                 jobject                 loaderObject,
       
   808                                 const char*             name,
       
   809                                 jclass                  classBeingRedefined,
       
   810                                 jobject                 protectionDomain,
       
   811                                 jint                    class_data_len,
       
   812                                 const unsigned char*    class_data,
       
   813                                 jint*                   new_class_data_len,
       
   814                                 unsigned char**         new_class_data,
       
   815                                 jboolean                is_retransformer) {
       
   816     jboolean        errorOutstanding        = JNI_FALSE;
       
   817     jstring         classNameStringObject   = NULL;
       
   818     jarray          classFileBufferObject   = NULL;
       
   819     jarray          transformedBufferObject = NULL;
       
   820     jsize           transformedBufferSize   = 0;
       
   821     unsigned char * resultBuffer            = NULL;
       
   822     jboolean        shouldRun               = JNI_FALSE;
       
   823 
       
   824     /* only do this if we aren't already in the middle of processing a class on this thread */
       
   825     shouldRun = tryToAcquireReentrancyToken(
       
   826                                 jvmti(agent),
       
   827                                 NULL);  /* this thread */
       
   828 
       
   829     if ( shouldRun ) {
       
   830         /* first marshall all the parameters */
       
   831         classNameStringObject = (*jnienv)->NewStringUTF(jnienv,
       
   832                                                         name);
       
   833         errorOutstanding = checkForAndClearThrowable(jnienv);
       
   834         jplis_assert_msg(!errorOutstanding, "can't create name string");
       
   835 
       
   836         if ( !errorOutstanding ) {
       
   837             classFileBufferObject = (*jnienv)->NewByteArray(jnienv,
       
   838                                                             class_data_len);
       
   839             errorOutstanding = checkForAndClearThrowable(jnienv);
       
   840             jplis_assert_msg(!errorOutstanding, "can't create byte array");
       
   841         }
       
   842 
       
   843         if ( !errorOutstanding ) {
       
   844             jbyte * typedBuffer = (jbyte *) class_data; /* nasty cast, dumb JNI interface, const missing */
       
   845                                                         /* The sign cast is safe. The const cast is dumb. */
       
   846             (*jnienv)->SetByteArrayRegion(  jnienv,
       
   847                                             classFileBufferObject,
       
   848                                             0,
       
   849                                             class_data_len,
       
   850                                             typedBuffer);
       
   851             errorOutstanding = checkForAndClearThrowable(jnienv);
       
   852             jplis_assert_msg(!errorOutstanding, "can't set byte array region");
       
   853         }
       
   854 
       
   855         /*  now call the JPL agents to do the transforming */
       
   856         /*  potential future optimization: may want to skip this if there are none */
       
   857         if ( !errorOutstanding ) {
       
   858             jobject moduleObject = NULL;
       
   859 
       
   860             if (classBeingRedefined == NULL) {
       
   861                 moduleObject = getModuleObject(jvmti(agent), loaderObject, name);
       
   862             } else {
       
   863                 // Redefine or retransform, InstrumentationImpl.transform() will use
       
   864                 // classBeingRedefined.getModule() to get the module.
       
   865             }
       
   866             jplis_assert(agent->mInstrumentationImpl != NULL);
       
   867             jplis_assert(agent->mTransform != NULL);
       
   868             transformedBufferObject = (*jnienv)->CallObjectMethod(
       
   869                                                 jnienv,
       
   870                                                 agent->mInstrumentationImpl,
       
   871                                                 agent->mTransform,
       
   872                                                 moduleObject,
       
   873                                                 loaderObject,
       
   874                                                 classNameStringObject,
       
   875                                                 classBeingRedefined,
       
   876                                                 protectionDomain,
       
   877                                                 classFileBufferObject,
       
   878                                                 is_retransformer);
       
   879             errorOutstanding = checkForAndClearThrowable(jnienv);
       
   880             jplis_assert_msg(!errorOutstanding, "transform method call failed");
       
   881         }
       
   882 
       
   883         /* Finally, unmarshall the parameters (if someone touched the buffer, tell the JVM) */
       
   884         if ( !errorOutstanding ) {
       
   885             if ( transformedBufferObject != NULL ) {
       
   886                 transformedBufferSize = (*jnienv)->GetArrayLength(  jnienv,
       
   887                                                                     transformedBufferObject);
       
   888                 errorOutstanding = checkForAndClearThrowable(jnienv);
       
   889                 jplis_assert_msg(!errorOutstanding, "can't get array length");
       
   890 
       
   891                 if ( !errorOutstanding ) {
       
   892                     /* allocate the response buffer with the JVMTI allocate call.
       
   893                      *  This is what the JVMTI spec says to do for Class File Load hook responses
       
   894                      */
       
   895                     jvmtiError  allocError = (*(jvmti(agent)))->Allocate(jvmti(agent),
       
   896                                                                              transformedBufferSize,
       
   897                                                                              &resultBuffer);
       
   898                     errorOutstanding = (allocError != JVMTI_ERROR_NONE);
       
   899                     jplis_assert_msg(!errorOutstanding, "can't allocate result buffer");
       
   900                 }
       
   901 
       
   902                 if ( !errorOutstanding ) {
       
   903                     (*jnienv)->GetByteArrayRegion(  jnienv,
       
   904                                                     transformedBufferObject,
       
   905                                                     0,
       
   906                                                     transformedBufferSize,
       
   907                                                     (jbyte *) resultBuffer);
       
   908                     errorOutstanding = checkForAndClearThrowable(jnienv);
       
   909                     jplis_assert_msg(!errorOutstanding, "can't get byte array region");
       
   910 
       
   911                     /* in this case, we will not return the buffer to the JVMTI,
       
   912                      * so we need to deallocate it ourselves
       
   913                      */
       
   914                     if ( errorOutstanding ) {
       
   915                         deallocate( jvmti(agent),
       
   916                                    (void*)resultBuffer);
       
   917                     }
       
   918                 }
       
   919 
       
   920                 if ( !errorOutstanding ) {
       
   921                     *new_class_data_len = (transformedBufferSize);
       
   922                     *new_class_data     = resultBuffer;
       
   923                 }
       
   924             }
       
   925         }
       
   926 
       
   927         /* release the token */
       
   928         releaseReentrancyToken( jvmti(agent),
       
   929                                 NULL);      /* this thread */
       
   930 
       
   931     }
       
   932 
       
   933     return;
       
   934 }
       
   935 
       
   936 /*
       
   937  *  Misc. internal utilities.
       
   938  */
       
   939 
       
   940 /*
       
   941  *  The only checked exceptions we can throw are ClassNotFoundException and
       
   942  *  UnmodifiableClassException. All others map to InternalError.
       
   943  */
       
   944 jthrowable
       
   945 redefineClassMapper(    JNIEnv *    jnienv,
       
   946                         jthrowable  throwableToMap) {
       
   947     jthrowable  mappedThrowable = NULL;
       
   948 
       
   949     jplis_assert(isSafeForJNICalls(jnienv));
       
   950     jplis_assert(!isUnchecked(jnienv, throwableToMap));
       
   951 
       
   952     if ( isInstanceofClassName( jnienv,
       
   953                                 throwableToMap,
       
   954                                 "java/lang/ClassNotFoundException") ) {
       
   955         mappedThrowable = throwableToMap;
       
   956     } else {
       
   957         if ( isInstanceofClassName( jnienv,
       
   958                                 throwableToMap,
       
   959                                 "java/lang/instrument/UnmodifiableClassException")) {
       
   960             mappedThrowable = throwableToMap;
       
   961         } else {
       
   962             jstring message = NULL;
       
   963 
       
   964             message = getMessageFromThrowable(jnienv, throwableToMap);
       
   965             mappedThrowable = createInternalError(jnienv, message);
       
   966         }
       
   967     }
       
   968 
       
   969     jplis_assert(isSafeForJNICalls(jnienv));
       
   970     return mappedThrowable;
       
   971 }
       
   972 
       
   973 jobjectArray
       
   974 getObjectArrayFromClasses(JNIEnv* jnienv, jclass* classes, jint classCount) {
       
   975     jclass          classArrayClass = NULL;
       
   976     jobjectArray    localArray      = NULL;
       
   977     jint            classIndex      = 0;
       
   978     jboolean        errorOccurred   = JNI_FALSE;
       
   979 
       
   980     /* get the class array class */
       
   981     classArrayClass = (*jnienv)->FindClass(jnienv, "java/lang/Class");
       
   982     errorOccurred = checkForThrowable(jnienv);
       
   983 
       
   984     if (!errorOccurred) {
       
   985         jplis_assert_msg(classArrayClass != NULL, "FindClass returned null class");
       
   986 
       
   987         /* create the array for the classes */
       
   988         localArray = (*jnienv)->NewObjectArray(jnienv, classCount, classArrayClass, NULL);
       
   989         errorOccurred = checkForThrowable(jnienv);
       
   990 
       
   991         if (!errorOccurred) {
       
   992             jplis_assert_msg(localArray != NULL, "NewObjectArray returned null array");
       
   993 
       
   994             /* now copy refs to all the classes and put them into the array */
       
   995             for (classIndex = 0; classIndex < classCount; classIndex++) {
       
   996                 /* put class into array */
       
   997                 (*jnienv)->SetObjectArrayElement(jnienv, localArray, classIndex, classes[classIndex]);
       
   998                 errorOccurred = checkForThrowable(jnienv);
       
   999 
       
  1000                 if (errorOccurred) {
       
  1001                     localArray = NULL;
       
  1002                     break;
       
  1003                 }
       
  1004             }
       
  1005         }
       
  1006     }
       
  1007 
       
  1008     return localArray;
       
  1009 }
       
  1010 
       
  1011 
       
  1012 /* Return the environment with the retransformation capability.
       
  1013  * Create it if it doesn't exist.
       
  1014  * Return NULL if it can't be created.
       
  1015  */
       
  1016 jvmtiEnv *
       
  1017 retransformableEnvironment(JPLISAgent * agent) {
       
  1018     jvmtiEnv *          retransformerEnv     = NULL;
       
  1019     jint                jnierror             = JNI_OK;
       
  1020     jvmtiCapabilities   desiredCapabilities;
       
  1021     jvmtiEventCallbacks callbacks;
       
  1022     jvmtiError          jvmtierror;
       
  1023 
       
  1024     if (agent->mRetransformEnvironment.mJVMTIEnv != NULL) {
       
  1025         return agent->mRetransformEnvironment.mJVMTIEnv;
       
  1026     }
       
  1027     jnierror = (*agent->mJVM)->GetEnv(  agent->mJVM,
       
  1028                                (void **) &retransformerEnv,
       
  1029                                JVMTI_VERSION_1_1);
       
  1030     if ( jnierror != JNI_OK ) {
       
  1031         return NULL;
       
  1032     }
       
  1033     jvmtierror = (*retransformerEnv)->GetCapabilities(retransformerEnv, &desiredCapabilities);
       
  1034     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
  1035     desiredCapabilities.can_retransform_classes = 1;
       
  1036     if (agent->mNativeMethodPrefixAdded) {
       
  1037         desiredCapabilities.can_set_native_method_prefix = 1;
       
  1038     }
       
  1039 
       
  1040     jvmtierror = (*retransformerEnv)->AddCapabilities(retransformerEnv, &desiredCapabilities);
       
  1041     if (jvmtierror != JVMTI_ERROR_NONE) {
       
  1042          /* cannot get the capability, dispose of the retransforming environment */
       
  1043         jvmtierror = (*retransformerEnv)->DisposeEnvironment(retransformerEnv);
       
  1044         jplis_assert(jvmtierror == JVMTI_ERROR_NOT_AVAILABLE);
       
  1045         return NULL;
       
  1046     }
       
  1047     memset(&callbacks, 0, sizeof(callbacks));
       
  1048     callbacks.ClassFileLoadHook = &eventHandlerClassFileLoadHook;
       
  1049 
       
  1050     jvmtierror = (*retransformerEnv)->SetEventCallbacks(retransformerEnv,
       
  1051                                                         &callbacks,
       
  1052                                                         sizeof(callbacks));
       
  1053     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
  1054     if (jvmtierror == JVMTI_ERROR_NONE) {
       
  1055         // install the retransforming environment
       
  1056         agent->mRetransformEnvironment.mJVMTIEnv = retransformerEnv;
       
  1057         agent->mRetransformEnvironment.mIsRetransformer = JNI_TRUE;
       
  1058 
       
  1059         // Make it for ClassFileLoadHook handling
       
  1060         jvmtierror = (*retransformerEnv)->SetEnvironmentLocalStorage(
       
  1061                                                        retransformerEnv,
       
  1062                                                        &(agent->mRetransformEnvironment));
       
  1063         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
  1064         if (jvmtierror == JVMTI_ERROR_NONE) {
       
  1065             return retransformerEnv;
       
  1066         }
       
  1067     }
       
  1068     return NULL;
       
  1069 }
       
  1070 
       
  1071 
       
  1072 /*
       
  1073  *  Underpinnings for native methods
       
  1074  */
       
  1075 
       
  1076 jboolean
       
  1077 isModifiableClass(JNIEnv * jnienv, JPLISAgent * agent, jclass clazz) {
       
  1078     jvmtiEnv *          jvmtienv = jvmti(agent);
       
  1079     jvmtiError          jvmtierror;
       
  1080     jboolean            is_modifiable = JNI_FALSE;
       
  1081 
       
  1082     jvmtierror = (*jvmtienv)->IsModifiableClass( jvmtienv,
       
  1083                                                  clazz,
       
  1084                                                  &is_modifiable);
       
  1085     check_phase_ret_false(jvmtierror);
       
  1086     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
  1087 
       
  1088     return is_modifiable;
       
  1089 }
       
  1090 
       
  1091 jboolean
       
  1092 isRetransformClassesSupported(JNIEnv * jnienv, JPLISAgent * agent) {
       
  1093     return agent->mRetransformEnvironment.mIsRetransformer;
       
  1094 }
       
  1095 
       
  1096 void
       
  1097 setHasRetransformableTransformers(JNIEnv * jnienv, JPLISAgent * agent, jboolean has) {
       
  1098     jvmtiEnv *          retransformerEnv     = retransformableEnvironment(agent);
       
  1099     jvmtiError          jvmtierror;
       
  1100 
       
  1101     jplis_assert(retransformerEnv != NULL);
       
  1102     jvmtierror = (*retransformerEnv)->SetEventNotificationMode(
       
  1103                                                     retransformerEnv,
       
  1104                                                     has? JVMTI_ENABLE : JVMTI_DISABLE,
       
  1105                                                     JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
       
  1106                                                     NULL /* all threads */);
       
  1107     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
  1108 }
       
  1109 
       
  1110 void
       
  1111 retransformClasses(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray classes) {
       
  1112     jvmtiEnv *  retransformerEnv     = retransformableEnvironment(agent);
       
  1113     jboolean    errorOccurred        = JNI_FALSE;
       
  1114     jvmtiError  errorCode            = JVMTI_ERROR_NONE;
       
  1115     jsize       numClasses           = 0;
       
  1116     jclass *    classArray           = NULL;
       
  1117 
       
  1118     /* This is supposed to be checked by caller, but just to be sure */
       
  1119     if (retransformerEnv == NULL) {
       
  1120         jplis_assert(retransformerEnv != NULL);
       
  1121         errorOccurred = JNI_TRUE;
       
  1122         errorCode = JVMTI_ERROR_MUST_POSSESS_CAPABILITY;
       
  1123     }
       
  1124 
       
  1125     /* This was supposed to be checked by caller too */
       
  1126     if (!errorOccurred && classes == NULL) {
       
  1127         jplis_assert(classes != NULL);
       
  1128         errorOccurred = JNI_TRUE;
       
  1129         errorCode = JVMTI_ERROR_NULL_POINTER;
       
  1130     }
       
  1131 
       
  1132     if (!errorOccurred) {
       
  1133         numClasses = (*jnienv)->GetArrayLength(jnienv, classes);
       
  1134         errorOccurred = checkForThrowable(jnienv);
       
  1135         jplis_assert(!errorOccurred);
       
  1136 
       
  1137         if (!errorOccurred && numClasses == 0) {
       
  1138             jplis_assert(numClasses != 0);
       
  1139             errorOccurred = JNI_TRUE;
       
  1140             errorCode = JVMTI_ERROR_NULL_POINTER;
       
  1141         }
       
  1142     }
       
  1143 
       
  1144     if (!errorOccurred) {
       
  1145         classArray = (jclass *) allocate(retransformerEnv,
       
  1146                                          numClasses * sizeof(jclass));
       
  1147         errorOccurred = (classArray == NULL);
       
  1148         jplis_assert(!errorOccurred);
       
  1149         if (errorOccurred) {
       
  1150             errorCode = JVMTI_ERROR_OUT_OF_MEMORY;
       
  1151         }
       
  1152     }
       
  1153 
       
  1154     if (!errorOccurred) {
       
  1155         jint index;
       
  1156         for (index = 0; index < numClasses; index++) {
       
  1157             classArray[index] = (*jnienv)->GetObjectArrayElement(jnienv, classes, index);
       
  1158             errorOccurred = checkForThrowable(jnienv);
       
  1159             jplis_assert(!errorOccurred);
       
  1160             if (errorOccurred) {
       
  1161                 break;
       
  1162             }
       
  1163 
       
  1164             if (classArray[index] == NULL) {
       
  1165                 jplis_assert(classArray[index] != NULL);
       
  1166                 errorOccurred = JNI_TRUE;
       
  1167                 errorCode = JVMTI_ERROR_NULL_POINTER;
       
  1168                 break;
       
  1169             }
       
  1170         }
       
  1171     }
       
  1172 
       
  1173     if (!errorOccurred) {
       
  1174         errorCode = (*retransformerEnv)->RetransformClasses(retransformerEnv,
       
  1175                                                             numClasses, classArray);
       
  1176         errorOccurred = (errorCode != JVMTI_ERROR_NONE);
       
  1177     }
       
  1178 
       
  1179     /* Give back the buffer if we allocated it.  Throw any exceptions after.
       
  1180      */
       
  1181     if (classArray != NULL) {
       
  1182         deallocate(retransformerEnv, (void*)classArray);
       
  1183     }
       
  1184 
       
  1185     if (errorCode != JVMTI_ERROR_NONE) {
       
  1186         createAndThrowThrowableFromJVMTIErrorCode(jnienv, errorCode);
       
  1187     }
       
  1188 
       
  1189     mapThrownThrowableIfNecessary(jnienv, redefineClassMapper);
       
  1190 }
       
  1191 
       
  1192 /*
       
  1193  *  Java code must not call this with a null list or a zero-length list.
       
  1194  */
       
  1195 void
       
  1196 redefineClasses(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray classDefinitions) {
       
  1197     jvmtiEnv*   jvmtienv                        = jvmti(agent);
       
  1198     jboolean    errorOccurred                   = JNI_FALSE;
       
  1199     jclass      classDefClass                   = NULL;
       
  1200     jmethodID   getDefinitionClassMethodID      = NULL;
       
  1201     jmethodID   getDefinitionClassFileMethodID  = NULL;
       
  1202     jvmtiClassDefinition* classDefs             = NULL;
       
  1203     jbyteArray* targetFiles                     = NULL;
       
  1204     jsize       numDefs                         = 0;
       
  1205 
       
  1206     jplis_assert(classDefinitions != NULL);
       
  1207 
       
  1208     numDefs = (*jnienv)->GetArrayLength(jnienv, classDefinitions);
       
  1209     errorOccurred = checkForThrowable(jnienv);
       
  1210     jplis_assert(!errorOccurred);
       
  1211 
       
  1212     if (!errorOccurred) {
       
  1213         jplis_assert(numDefs > 0);
       
  1214         /* get method IDs for methods to call on class definitions */
       
  1215         classDefClass = (*jnienv)->FindClass(jnienv, "java/lang/instrument/ClassDefinition");
       
  1216         errorOccurred = checkForThrowable(jnienv);
       
  1217         jplis_assert(!errorOccurred);
       
  1218     }
       
  1219 
       
  1220     if (!errorOccurred) {
       
  1221         getDefinitionClassMethodID = (*jnienv)->GetMethodID(    jnienv,
       
  1222                                                 classDefClass,
       
  1223                                                 "getDefinitionClass",
       
  1224                                                 "()Ljava/lang/Class;");
       
  1225         errorOccurred = checkForThrowable(jnienv);
       
  1226         jplis_assert(!errorOccurred);
       
  1227     }
       
  1228 
       
  1229     if (!errorOccurred) {
       
  1230         getDefinitionClassFileMethodID = (*jnienv)->GetMethodID(    jnienv,
       
  1231                                                     classDefClass,
       
  1232                                                     "getDefinitionClassFile",
       
  1233                                                     "()[B");
       
  1234         errorOccurred = checkForThrowable(jnienv);
       
  1235         jplis_assert(!errorOccurred);
       
  1236     }
       
  1237 
       
  1238     if (!errorOccurred) {
       
  1239         classDefs = (jvmtiClassDefinition *) allocate(
       
  1240                                                 jvmtienv,
       
  1241                                                 numDefs * sizeof(jvmtiClassDefinition));
       
  1242         errorOccurred = (classDefs == NULL);
       
  1243         jplis_assert(!errorOccurred);
       
  1244         if ( errorOccurred ) {
       
  1245             createAndThrowThrowableFromJVMTIErrorCode(jnienv, JVMTI_ERROR_OUT_OF_MEMORY);
       
  1246         }
       
  1247 
       
  1248         else {
       
  1249             /*
       
  1250              * We have to save the targetFile values that we compute so
       
  1251              * that we can release the class_bytes arrays that are
       
  1252              * returned by GetByteArrayElements(). In case of a JNI
       
  1253              * error, we can't (easily) recompute the targetFile values
       
  1254              * and we still want to free any memory we allocated.
       
  1255              */
       
  1256             targetFiles = (jbyteArray *) allocate(jvmtienv,
       
  1257                                                   numDefs * sizeof(jbyteArray));
       
  1258             errorOccurred = (targetFiles == NULL);
       
  1259             jplis_assert(!errorOccurred);
       
  1260             if ( errorOccurred ) {
       
  1261                 deallocate(jvmtienv, (void*)classDefs);
       
  1262                 createAndThrowThrowableFromJVMTIErrorCode(jnienv,
       
  1263                     JVMTI_ERROR_OUT_OF_MEMORY);
       
  1264             }
       
  1265             else {
       
  1266                 jint i, j;
       
  1267 
       
  1268                 // clear classDefs so we can correctly free memory during errors
       
  1269                 memset(classDefs, 0, numDefs * sizeof(jvmtiClassDefinition));
       
  1270 
       
  1271                 for (i = 0; i < numDefs; i++) {
       
  1272                     jclass      classDef    = NULL;
       
  1273 
       
  1274                     classDef = (*jnienv)->GetObjectArrayElement(jnienv, classDefinitions, i);
       
  1275                     errorOccurred = checkForThrowable(jnienv);
       
  1276                     jplis_assert(!errorOccurred);
       
  1277                     if (errorOccurred) {
       
  1278                         break;
       
  1279                     }
       
  1280 
       
  1281                     classDefs[i].klass = (*jnienv)->CallObjectMethod(jnienv, classDef, getDefinitionClassMethodID);
       
  1282                     errorOccurred = checkForThrowable(jnienv);
       
  1283                     jplis_assert(!errorOccurred);
       
  1284                     if (errorOccurred) {
       
  1285                         break;
       
  1286                     }
       
  1287 
       
  1288                     targetFiles[i] = (*jnienv)->CallObjectMethod(jnienv, classDef, getDefinitionClassFileMethodID);
       
  1289                     errorOccurred = checkForThrowable(jnienv);
       
  1290                     jplis_assert(!errorOccurred);
       
  1291                     if (errorOccurred) {
       
  1292                         break;
       
  1293                     }
       
  1294 
       
  1295                     classDefs[i].class_byte_count = (*jnienv)->GetArrayLength(jnienv, targetFiles[i]);
       
  1296                     errorOccurred = checkForThrowable(jnienv);
       
  1297                     jplis_assert(!errorOccurred);
       
  1298                     if (errorOccurred) {
       
  1299                         break;
       
  1300                     }
       
  1301 
       
  1302                     /*
       
  1303                      * Allocate class_bytes last so we don't have to free
       
  1304                      * memory on a partial row error.
       
  1305                      */
       
  1306                     classDefs[i].class_bytes = (unsigned char*)(*jnienv)->GetByteArrayElements(jnienv, targetFiles[i], NULL);
       
  1307                     errorOccurred = checkForThrowable(jnienv);
       
  1308                     jplis_assert(!errorOccurred);
       
  1309                     if (errorOccurred) {
       
  1310                         break;
       
  1311                     }
       
  1312                 }
       
  1313 
       
  1314                 if (!errorOccurred) {
       
  1315                     jvmtiError  errorCode = JVMTI_ERROR_NONE;
       
  1316                     errorCode = (*jvmtienv)->RedefineClasses(jvmtienv, numDefs, classDefs);
       
  1317                     if (errorCode == JVMTI_ERROR_WRONG_PHASE) {
       
  1318                         /* insulate caller from the wrong phase error */
       
  1319                         errorCode = JVMTI_ERROR_NONE;
       
  1320                     } else {
       
  1321                         errorOccurred = (errorCode != JVMTI_ERROR_NONE);
       
  1322                         if ( errorOccurred ) {
       
  1323                             createAndThrowThrowableFromJVMTIErrorCode(jnienv, errorCode);
       
  1324                         }
       
  1325                     }
       
  1326                 }
       
  1327 
       
  1328                 /*
       
  1329                  * Cleanup memory that we allocated above. If we had a
       
  1330                  * JNI error, a JVM/TI error or no errors, index 'i'
       
  1331                  * tracks how far we got in processing the classDefs
       
  1332                  * array. Note:  ReleaseByteArrayElements() is safe to
       
  1333                  * call with a JNI exception pending.
       
  1334                  */
       
  1335                 for (j = 0; j < i; j++) {
       
  1336                     if ((jbyte *)classDefs[j].class_bytes != NULL) {
       
  1337                         (*jnienv)->ReleaseByteArrayElements(jnienv,
       
  1338                             targetFiles[j], (jbyte *)classDefs[j].class_bytes,
       
  1339                             0 /* copy back and free */);
       
  1340                         /*
       
  1341                          * Only check for error if we didn't already have one
       
  1342                          * so we don't overwrite errorOccurred.
       
  1343                          */
       
  1344                         if (!errorOccurred) {
       
  1345                             errorOccurred = checkForThrowable(jnienv);
       
  1346                             jplis_assert(!errorOccurred);
       
  1347                         }
       
  1348                     }
       
  1349                 }
       
  1350                 deallocate(jvmtienv, (void*)targetFiles);
       
  1351                 deallocate(jvmtienv, (void*)classDefs);
       
  1352             }
       
  1353         }
       
  1354     }
       
  1355 
       
  1356     mapThrownThrowableIfNecessary(jnienv, redefineClassMapper);
       
  1357 }
       
  1358 
       
  1359 /* Cheesy sharing. ClassLoader may be null. */
       
  1360 jobjectArray
       
  1361 commonGetClassList( JNIEnv *            jnienv,
       
  1362                     JPLISAgent *        agent,
       
  1363                     jobject             classLoader,
       
  1364                     ClassListFetcher    fetcher) {
       
  1365     jvmtiEnv *      jvmtienv        = jvmti(agent);
       
  1366     jboolean        errorOccurred   = JNI_FALSE;
       
  1367     jvmtiError      jvmtierror      = JVMTI_ERROR_NONE;
       
  1368     jint            classCount      = 0;
       
  1369     jclass *        classes         = NULL;
       
  1370     jobjectArray    localArray      = NULL;
       
  1371 
       
  1372     /* retrieve the classes from the JVMTI agent */
       
  1373     jvmtierror = (*fetcher)( jvmtienv,
       
  1374                         classLoader,
       
  1375                         &classCount,
       
  1376                         &classes);
       
  1377     check_phase_ret_blob(jvmtierror, localArray);
       
  1378     errorOccurred = (jvmtierror != JVMTI_ERROR_NONE);
       
  1379     jplis_assert(!errorOccurred);
       
  1380 
       
  1381     if ( errorOccurred ) {
       
  1382         createAndThrowThrowableFromJVMTIErrorCode(jnienv, jvmtierror);
       
  1383     } else {
       
  1384         localArray = getObjectArrayFromClasses( jnienv,
       
  1385                                                 classes,
       
  1386                                                 classCount);
       
  1387         errorOccurred = checkForThrowable(jnienv);
       
  1388         jplis_assert(!errorOccurred);
       
  1389 
       
  1390         /* do this whether or not we saw a problem */
       
  1391         deallocate(jvmtienv, (void*)classes);
       
  1392     }
       
  1393 
       
  1394     mapThrownThrowableIfNecessary(jnienv, mapAllCheckedToInternalErrorMapper);
       
  1395     return localArray;
       
  1396 
       
  1397 }
       
  1398 
       
  1399 jvmtiError
       
  1400 getAllLoadedClassesClassListFetcher(    jvmtiEnv *  jvmtienv,
       
  1401                                         jobject     classLoader,
       
  1402                                         jint *      classCount,
       
  1403                                         jclass **   classes) {
       
  1404     return (*jvmtienv)->GetLoadedClasses(jvmtienv, classCount, classes);
       
  1405 }
       
  1406 
       
  1407 jobjectArray
       
  1408 getAllLoadedClasses(JNIEnv * jnienv, JPLISAgent * agent) {
       
  1409     return commonGetClassList(  jnienv,
       
  1410                                 agent,
       
  1411                                 NULL,
       
  1412                                 getAllLoadedClassesClassListFetcher);
       
  1413 }
       
  1414 
       
  1415 jvmtiError
       
  1416 getInitiatedClassesClassListFetcher(    jvmtiEnv *  jvmtienv,
       
  1417                                         jobject     classLoader,
       
  1418                                         jint *      classCount,
       
  1419                                         jclass **   classes) {
       
  1420     return (*jvmtienv)->GetClassLoaderClasses(jvmtienv, classLoader, classCount, classes);
       
  1421 }
       
  1422 
       
  1423 
       
  1424 jobjectArray
       
  1425 getInitiatedClasses(JNIEnv * jnienv, JPLISAgent * agent, jobject classLoader) {
       
  1426     return commonGetClassList(  jnienv,
       
  1427                                 agent,
       
  1428                                 classLoader,
       
  1429                                 getInitiatedClassesClassListFetcher);
       
  1430 }
       
  1431 
       
  1432 jlong
       
  1433 getObjectSize(JNIEnv * jnienv, JPLISAgent * agent, jobject objectToSize) {
       
  1434     jvmtiEnv *  jvmtienv    = jvmti(agent);
       
  1435     jlong       objectSize  = -1;
       
  1436     jvmtiError  jvmtierror  = JVMTI_ERROR_NONE;
       
  1437 
       
  1438     jvmtierror = (*jvmtienv)->GetObjectSize(jvmtienv, objectToSize, &objectSize);
       
  1439     check_phase_ret_0(jvmtierror);
       
  1440     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
       
  1441     if ( jvmtierror != JVMTI_ERROR_NONE ) {
       
  1442         createAndThrowThrowableFromJVMTIErrorCode(jnienv, jvmtierror);
       
  1443     }
       
  1444 
       
  1445     mapThrownThrowableIfNecessary(jnienv, mapAllCheckedToInternalErrorMapper);
       
  1446     return objectSize;
       
  1447 }
       
  1448 
       
  1449 void
       
  1450 appendToClassLoaderSearch(JNIEnv * jnienv, JPLISAgent * agent, jstring jarFile, jboolean isBootLoader)
       
  1451 {
       
  1452     jvmtiEnv *  jvmtienv    = jvmti(agent);
       
  1453     jboolean    errorOutstanding;
       
  1454     jvmtiError  jvmtierror;
       
  1455     const char* utf8Chars;
       
  1456     jsize       utf8Len;
       
  1457     jboolean    isCopy;
       
  1458     char        platformChars[MAXPATHLEN];
       
  1459     int         platformLen;
       
  1460 
       
  1461     utf8Len = (*jnienv)->GetStringUTFLength(jnienv, jarFile);
       
  1462     errorOutstanding = checkForAndClearThrowable(jnienv);
       
  1463 
       
  1464     if (!errorOutstanding) {
       
  1465         utf8Chars = (*jnienv)->GetStringUTFChars(jnienv, jarFile, &isCopy);
       
  1466         errorOutstanding = checkForAndClearThrowable(jnienv);
       
  1467 
       
  1468         if (!errorOutstanding && utf8Chars != NULL) {
       
  1469             /*
       
  1470              * JVMTI spec'ed to use modified UTF8. At this time this is not implemented
       
  1471              * the platform encoding is used.
       
  1472              */
       
  1473             platformLen = convertUft8ToPlatformString((char*)utf8Chars, utf8Len, platformChars, MAXPATHLEN);
       
  1474             if (platformLen < 0) {
       
  1475                 createAndThrowInternalError(jnienv);
       
  1476                 return;
       
  1477             }
       
  1478 
       
  1479             (*jnienv)->ReleaseStringUTFChars(jnienv, jarFile, utf8Chars);
       
  1480             errorOutstanding = checkForAndClearThrowable(jnienv);
       
  1481 
       
  1482             if (!errorOutstanding) {
       
  1483 
       
  1484                 if (isBootLoader) {
       
  1485                     jvmtierror = (*jvmtienv)->AddToBootstrapClassLoaderSearch(jvmtienv, platformChars);
       
  1486                 } else {
       
  1487                     jvmtierror = (*jvmtienv)->AddToSystemClassLoaderSearch(jvmtienv, platformChars);
       
  1488                 }
       
  1489                 check_phase_ret(jvmtierror);
       
  1490 
       
  1491                 if ( jvmtierror != JVMTI_ERROR_NONE ) {
       
  1492                     createAndThrowThrowableFromJVMTIErrorCode(jnienv, jvmtierror);
       
  1493                 }
       
  1494             }
       
  1495         }
       
  1496     }
       
  1497 
       
  1498     mapThrownThrowableIfNecessary(jnienv, mapAllCheckedToInternalErrorMapper);
       
  1499 }
       
  1500 
       
  1501 /*
       
  1502  *  Set the prefixes used to wrap native methods (so they can be instrumented).
       
  1503  *  Each transform can set a prefix, any that have been set come in as prefixArray.
       
  1504  *  Convert them in native strings in a native array then call JVM TI.
       
  1505  *  One a given call, this function handles either the prefixes for retransformable
       
  1506  *  transforms or for normal transforms.
       
  1507  */
       
  1508 void
       
  1509 setNativeMethodPrefixes(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray prefixArray,
       
  1510                         jboolean isRetransformable) {
       
  1511     jvmtiEnv*   jvmtienv;
       
  1512     jvmtiError  err                             = JVMTI_ERROR_NONE;
       
  1513     jsize       arraySize;
       
  1514     jboolean    errorOccurred                   = JNI_FALSE;
       
  1515 
       
  1516     jplis_assert(prefixArray != NULL);
       
  1517 
       
  1518     if (isRetransformable) {
       
  1519         jvmtienv = agent->mRetransformEnvironment.mJVMTIEnv;
       
  1520     } else {
       
  1521         jvmtienv = agent->mNormalEnvironment.mJVMTIEnv;
       
  1522     }
       
  1523     arraySize = (*jnienv)->GetArrayLength(jnienv, prefixArray);
       
  1524     errorOccurred = checkForThrowable(jnienv);
       
  1525     jplis_assert(!errorOccurred);
       
  1526 
       
  1527     if (!errorOccurred) {
       
  1528         /* allocate the native to hold the native prefixes */
       
  1529         const char** prefixes = (const char**) allocate(jvmtienv,
       
  1530                                                         arraySize * sizeof(char*));
       
  1531         /* since JNI ReleaseStringUTFChars needs the jstring from which the native
       
  1532          * string was allocated, we store them in a parallel array */
       
  1533         jstring* originForRelease = (jstring*) allocate(jvmtienv,
       
  1534                                                         arraySize * sizeof(jstring));
       
  1535         errorOccurred = (prefixes == NULL || originForRelease == NULL);
       
  1536         jplis_assert(!errorOccurred);
       
  1537         if ( errorOccurred ) {
       
  1538             createAndThrowThrowableFromJVMTIErrorCode(jnienv, JVMTI_ERROR_OUT_OF_MEMORY);
       
  1539         }
       
  1540         else {
       
  1541             jint inx = 0;
       
  1542             jint i;
       
  1543             for (i = 0; i < arraySize; i++) {
       
  1544                 jstring      prefixStr  = NULL;
       
  1545                 const char*  prefix;
       
  1546                 jsize        prefixLen;
       
  1547                 jboolean     isCopy;
       
  1548 
       
  1549                 prefixStr = (jstring) ((*jnienv)->GetObjectArrayElement(jnienv,
       
  1550                                                                         prefixArray, i));
       
  1551                 errorOccurred = checkForThrowable(jnienv);
       
  1552                 jplis_assert(!errorOccurred);
       
  1553                 if (errorOccurred) {
       
  1554                     break;
       
  1555                 }
       
  1556                 if (prefixStr == NULL) {
       
  1557                     continue;
       
  1558                 }
       
  1559 
       
  1560                 prefixLen = (*jnienv)->GetStringUTFLength(jnienv, prefixStr);
       
  1561                 errorOccurred = checkForThrowable(jnienv);
       
  1562                 jplis_assert(!errorOccurred);
       
  1563                 if (errorOccurred) {
       
  1564                     break;
       
  1565                 }
       
  1566 
       
  1567                 if (prefixLen > 0) {
       
  1568                     prefix = (*jnienv)->GetStringUTFChars(jnienv, prefixStr, &isCopy);
       
  1569                     errorOccurred = checkForThrowable(jnienv);
       
  1570                     jplis_assert(!errorOccurred);
       
  1571                     if (!errorOccurred && prefix != NULL) {
       
  1572                         prefixes[inx] = prefix;
       
  1573                         originForRelease[inx] = prefixStr;
       
  1574                         ++inx;
       
  1575                     }
       
  1576                 }
       
  1577             }
       
  1578 
       
  1579             err = (*jvmtienv)->SetNativeMethodPrefixes(jvmtienv, inx, (char**)prefixes);
       
  1580             /* can be called from any phase */
       
  1581             jplis_assert(err == JVMTI_ERROR_NONE);
       
  1582 
       
  1583             for (i = 0; i < inx; i++) {
       
  1584               (*jnienv)->ReleaseStringUTFChars(jnienv, originForRelease[i], prefixes[i]);
       
  1585             }
       
  1586         }
       
  1587         deallocate(jvmtienv, (void*)prefixes);
       
  1588         deallocate(jvmtienv, (void*)originForRelease);
       
  1589     }
       
  1590 }