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