| /* |
| * Copyright (c) 2003, 2016, 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 |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /* |
| * Copyright 2003 Wily Technology, Inc. |
| */ |
| |
| #ifndef _JPLISAGENT_H_ |
| #define _JPLISAGENT_H_ |
| |
| #include <jni.h> |
| #include <jvmti.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /* |
| * The JPLISAgent manages the initialization all of the Java programming language Agents. |
| * It also supports the native method bridge between the JPLIS and the JVMTI. |
| * It maintains a single JVMTI Env that all JPL agents share. |
| * It parses command line requests and creates individual Java agents. |
| */ |
| |
| |
| /* |
| * Forward definitions |
| */ |
| struct _JPLISAgent; |
| |
| typedef struct _JPLISAgent JPLISAgent; |
| typedef struct _JPLISEnvironment JPLISEnvironment; |
| |
| |
| /* constants for class names and methods names and such |
| these all must stay in sync with Java code & interfaces |
| */ |
| #define JPLIS_INSTRUMENTIMPL_CLASSNAME "sun/instrument/InstrumentationImpl" |
| #define JPLIS_INSTRUMENTIMPL_CONSTRUCTOR_METHODNAME "<init>" |
| #define JPLIS_INSTRUMENTIMPL_CONSTRUCTOR_METHODSIGNATURE "(JZZ)V" |
| #define JPLIS_INSTRUMENTIMPL_PREMAININVOKER_METHODNAME "loadClassAndCallPremain" |
| #define JPLIS_INSTRUMENTIMPL_PREMAININVOKER_METHODSIGNATURE "(Ljava/lang/String;Ljava/lang/String;)V" |
| #define JPLIS_INSTRUMENTIMPL_AGENTMAININVOKER_METHODNAME "loadClassAndCallAgentmain" |
| #define JPLIS_INSTRUMENTIMPL_AGENTMAININVOKER_METHODSIGNATURE "(Ljava/lang/String;Ljava/lang/String;)V" |
| #define JPLIS_INSTRUMENTIMPL_TRANSFORM_METHODNAME "transform" |
| #define JPLIS_INSTRUMENTIMPL_TRANSFORM_METHODSIGNATURE \ |
| "(Ljava/lang/Module;Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/Class;Ljava/security/ProtectionDomain;[BZ)[B" |
| |
| |
| /* |
| * Error messages |
| */ |
| #define JPLIS_ERRORMESSAGE_CANNOTSTART "processing of -javaagent failed" |
| |
| |
| /* |
| * Our initialization errors |
| */ |
| typedef enum { |
| JPLIS_INIT_ERROR_NONE, |
| JPLIS_INIT_ERROR_CANNOT_CREATE_NATIVE_AGENT, |
| JPLIS_INIT_ERROR_FAILURE, |
| JPLIS_INIT_ERROR_ALLOCATION_FAILURE, |
| JPLIS_INIT_ERROR_AGENT_CLASS_NOT_SPECIFIED |
| } JPLISInitializationError; |
| |
| |
| struct _JPLISEnvironment { |
| jvmtiEnv * mJVMTIEnv; /* the JVM TI environment */ |
| JPLISAgent * mAgent; /* corresponding agent */ |
| jboolean mIsRetransformer; /* indicates if special environment */ |
| }; |
| |
| struct _JPLISAgent { |
| JavaVM * mJVM; /* handle to the JVM */ |
| JPLISEnvironment mNormalEnvironment; /* for every thing but retransform stuff */ |
| JPLISEnvironment mRetransformEnvironment;/* for retransform stuff only */ |
| jobject mInstrumentationImpl; /* handle to the Instrumentation instance */ |
| jmethodID mPremainCaller; /* method on the InstrumentationImpl that does the premain stuff (cached to save lots of lookups) */ |
| jmethodID mAgentmainCaller; /* method on the InstrumentationImpl for agents loaded via attach mechanism */ |
| jmethodID mTransform; /* method on the InstrumentationImpl that does the class file transform */ |
| jboolean mRedefineAvailable; /* cached answer to "does this agent support redefine" */ |
| jboolean mRedefineAdded; /* indicates if can_redefine_classes capability has been added */ |
| jboolean mNativeMethodPrefixAvailable; /* cached answer to "does this agent support prefixing" */ |
| jboolean mNativeMethodPrefixAdded; /* indicates if can_set_native_method_prefix capability has been added */ |
| char const * mAgentClassName; /* agent class name */ |
| char const * mOptionsString; /* -javaagent options string */ |
| const char * mJarfile; /* agent jar file name */ |
| }; |
| |
| /* |
| * JVMTI event handlers |
| */ |
| |
| /* VMInit event handler. Installed during OnLoad, then removed during VMInit. */ |
| extern void JNICALL |
| eventHandlerVMInit( jvmtiEnv * jvmtienv, |
| JNIEnv * jnienv, |
| jthread thread); |
| |
| /* ClassFileLoadHook event handler. Installed during VMInit, then left in place forever. */ |
| extern void JNICALL |
| eventHandlerClassFileLoadHook( jvmtiEnv * jvmtienv, |
| JNIEnv * jnienv, |
| jclass class_being_redefined, |
| jobject loader, |
| const char* name, |
| jobject protectionDomain, |
| jint class_data_len, |
| const unsigned char* class_data, |
| jint* new_class_data_len, |
| unsigned char** new_class_data); |
| |
| /* |
| * Main entry points for the JPLIS JVMTI agent code |
| */ |
| |
| /* looks up the environment instance. returns null if there isn't one */ |
| extern JPLISEnvironment * |
| getJPLISEnvironment(jvmtiEnv * jvmtienv); |
| |
| /* Creates a new JPLIS agent. |
| * Returns error if the agent cannot be created and initialized. |
| * The JPLISAgent* pointed to by agent_ptr is set to the new broker, |
| * or NULL if an error has occurred. |
| */ |
| extern JPLISInitializationError |
| createNewJPLISAgent(JavaVM * vm, JPLISAgent **agent_ptr); |
| |
| /* Adds can_redefine_classes capability */ |
| extern void |
| addRedefineClassesCapability(JPLISAgent * agent); |
| |
| /* Add the can_set_native_method_prefix capability */ |
| extern void |
| addNativeMethodPrefixCapability(JPLISAgent * agent); |
| |
| /* Add the can_maintain_original_method_order capability (for testing) */ |
| extern void |
| addOriginalMethodOrderCapability(JPLISAgent * agent); |
| |
| |
| /* Our JPLIS agent is paralleled by a Java InstrumentationImpl instance. |
| * This routine uses JNI to create and initialized the Java instance. |
| * Returns true if it succeeds, false otherwise. |
| */ |
| extern jboolean |
| createInstrumentationImpl( JNIEnv * jnienv, |
| JPLISAgent * agent); |
| |
| |
| /* during OnLoad phase (command line parsing) |
| * record the parameters of -javaagent |
| */ |
| extern JPLISInitializationError |
| recordCommandLineData( JPLISAgent * agent, |
| const char * agentClass, |
| const char * optionsString ); |
| |
| /* Swaps the start phase event handlers out and the live phase event handlers in. |
| * Also used in attach to enabled live phase event handlers. |
| * Returns true if it succeeds, false otherwise. |
| */ |
| extern jboolean |
| setLivePhaseEventHandlers( JPLISAgent * agent); |
| |
| /* Loads the Java agent according to the already processed command line. For each, |
| * loads the Java agent class, then calls the premain method. |
| * Returns true if all Java agent classes are loaded and all premain methods complete with no exceptions, |
| * false otherwise. |
| */ |
| extern jboolean |
| startJavaAgent( JPLISAgent * agent, |
| JNIEnv * jnienv, |
| const char * classname, |
| const char * optionsString, |
| jmethodID agentMainMethod); |
| |
| |
| /* during VMInit processing |
| * this is how the invocation engine (callback wrapper) tells us to start up all the javaagents |
| */ |
| extern jboolean |
| processJavaStart( JPLISAgent * agent, |
| JNIEnv * jnienv); |
| |
| /* on an ongoing basis, |
| * this is how the invocation engine (callback wrapper) tells us to process a class file |
| */ |
| extern void |
| transformClassFile( JPLISAgent * agent, |
| JNIEnv * jnienv, |
| jobject loader, |
| const char* name, |
| jclass classBeingRedefined, |
| jobject protectionDomain, |
| jint class_data_len, |
| const unsigned char* class_data, |
| jint* new_class_data_len, |
| unsigned char** new_class_data, |
| jboolean is_retransformer); |
| |
| /* on an ongoing basis, |
| * Return the environment with the retransformation capability. |
| * Create it if it doesn't exist. |
| */ |
| extern jvmtiEnv * |
| retransformableEnvironment(JPLISAgent * agent); |
| |
| /* on an ongoing basis, |
| * these are implementations of the Instrumentation services. |
| * Most are simple covers for JVMTI access services. These are the guts of the InstrumentationImpl |
| * native methods. |
| */ |
| extern jboolean |
| isModifiableClass(JNIEnv * jnienv, JPLISAgent * agent, jclass clazz); |
| |
| extern jboolean |
| isRetransformClassesSupported(JNIEnv * jnienv, JPLISAgent * agent); |
| |
| extern void |
| setHasRetransformableTransformers(JNIEnv * jnienv, JPLISAgent * agent, jboolean has); |
| |
| extern void |
| retransformClasses(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray classes); |
| |
| extern void |
| redefineClasses(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray classDefinitions); |
| |
| extern jobjectArray |
| getAllLoadedClasses(JNIEnv * jnienv, JPLISAgent * agent); |
| |
| extern jobjectArray |
| getInitiatedClasses(JNIEnv * jnienv, JPLISAgent * agent, jobject classLoader); |
| |
| extern jlong |
| getObjectSize(JNIEnv * jnienv, JPLISAgent * agent, jobject objectToSize); |
| |
| extern void |
| appendToClassLoaderSearch(JNIEnv * jnienv, JPLISAgent * agent, jstring jarFile, jboolean isBootLoader); |
| |
| extern void |
| setNativeMethodPrefixes(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray prefixArray, |
| jboolean isRetransformable); |
| |
| #define jvmti(a) a->mNormalEnvironment.mJVMTIEnv |
| |
| /* |
| * A set of macros for insulating the JLI method callers from |
| * JVMTI_ERROR_WRONG_PHASE return codes. |
| */ |
| |
| /* for a JLI method where "blob" is executed before simply returning */ |
| #define check_phase_blob_ret(ret, blob) \ |
| if ((ret) == JVMTI_ERROR_WRONG_PHASE) { \ |
| blob; \ |
| return; \ |
| } |
| |
| /* for a JLI method where simply returning is benign */ |
| #define check_phase_ret(ret) \ |
| if ((ret) == JVMTI_ERROR_WRONG_PHASE) { \ |
| return; \ |
| } |
| |
| /* for a JLI method where returning zero (0) is benign */ |
| #define check_phase_ret_0(ret) \ |
| if ((ret) == JVMTI_ERROR_WRONG_PHASE) { \ |
| return 0; \ |
| } |
| |
| /* for a JLI method where returning one (1) is benign */ |
| #define check_phase_ret_1(ret) \ |
| if ((ret) == JVMTI_ERROR_WRONG_PHASE) { \ |
| return 1; \ |
| } |
| |
| /* for a case where a specific "blob" must be returned */ |
| #define check_phase_ret_blob(ret, blob) \ |
| if ((ret) == JVMTI_ERROR_WRONG_PHASE) { \ |
| return (blob); \ |
| } |
| |
| /* for a JLI method where returning false is benign */ |
| #define check_phase_ret_false(ret) \ |
| if ((ret) == JVMTI_ERROR_WRONG_PHASE) { \ |
| return (jboolean) 0; \ |
| } |
| |
| #ifdef __cplusplus |
| } /* extern "C" */ |
| #endif /* __cplusplus */ |
| |
| |
| #endif |