view agent/src/oopUtil.hpp @ 41:0c499e72a72d

Bug 2376: Deadlock finder needs to return a original _thread_state to HotSpot VM. reviewed-by: yasuenag
author KUBOTA Yuji <kubota.yuji@lab.ntt.co.jp>
date Fri, 22 May 2015 11:59:18 +0900
parents 48632080be2a
children 79f42583c31c
line wrap: on
line source

/*!
 * \file oopUtil.hpp
 * \brief This file is used to getting information inner JVM.<br>
 * Copyright (C) 2011-2015 Nippon Telegraph and Telephone Corporation
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program 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 for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */

#ifndef _OOP_UTIL_H
#define _OOP_UTIL_H

#include <jni.h>
#include <jvmti.h>

#include <stdint.h>
#include <sys/types.h>

#include "symbolFinder.hpp"
#include "vmStructScanner.hpp"
#include "jvmInfo.hpp"
#include "bitMapMarker.hpp"

/* Typedef. */

/* Inner function type. */

/*!
 * \brief This function is C++ heap class member.<br>
 *        So 1st arg must be set instance.
 * \param thisptr [in] SharedHeap/ParallelScavengeHeap object instance.
 * \param oop     [in] Java object.
 * \return Java object is existing in perm gen.
 */
typedef bool (*THeap_IsInPermanent)(void *thisptr, void *oop);

/*!
 * \brief This function is C++ JvmtiEnv class member.<br>
 *        So 1st arg must be set instance.<br>
 *        jvmtiError JvmtiEnv::GetObjectSize(jobject object, jlong* size_ptr)
 * \param thisptr  [in]  JvmtiEnv object instance.
 * \param object   [in]  Java object.
 * \param size_ptr [out] Pointer of java object's size.
 * \return Java object's size.
 */
typedef int (*TJvmtiEnv_GetObjectSize)(void *thisptr, jobject object,
    jlong *size_ptr);

/*!
 * \brief This function is java_lang_Class class member.<br>
 *        void *java_lang_Class::as_klassOop(void *mirror);
 * \param mirror [in] Java object mirror.
 * \return KlassOop of java object mirror.
 */
typedef void *(*TJavaLangClass_AsKlassOop)(void *mirror);

/* Callback function type. */

/*!
 * \brief This function is for heap object callback.
 * \param oop  [in] Java heap object(Inner class format).
 * \param data [in] User expected data. Always this value is NULL.
 */
typedef void (*THeapObjectCallback)(void *oop, void* data);

/*!
 * \brief This function is for class oop adjust callback by GC.
 * \param oldOop [in] Old pointer of java class object(KlassOopDesc).
 * \param newOop [in] New pointer of java class object(KlassOopDesc).
 */
typedef void (*TKlassAdjustCallback)(void *oldOop, void *newOop);

/*!
 * \brief This function type is for common callback.
 */
typedef void (*TCommonCallback)(void);

/*!
 * \brief This function is for get classloader.<br>
 *        E.g. instanceKlass::class_loader()<br>
 *             objArrayKlass::class_loader()<br>
 * \param klassOop [in] Pointer of java class object(KlassOopDesc).
 * \return Java heap object which is class loader load expected the class.
 */
typedef void *(*TGetClassLoader)(void *klassOop);

/* Other type. */

/*!
 * \brief Override function information structure.
 */
typedef struct {
    const char *vtableSymbol; /*!< Symbol string of target class.            */
    void **vtable;            /*!< Pointer of C++ vtable.                    */
    const char *funcSymbol;   /*!< Symbol string of target function.         */
    void *overrideFunc;       /*!< Pointer of override function.             */
    void *originalFunc;       /*!< Pointer of callback target.               */
    void *afterFunc;          /*!< Pointer of callback after invoke target.  */
    bool isVTableWritable;    /*!< Is vtable already writable?               */
}
#ifdef __LP64__
__attribute__((aligned(16)))
#endif
THookFunctionInfo;

/*!
 * \brief This structure is expressing garbage collector state.
 */
typedef enum{
    gcStart  = 1, /*!< Garbage collector is start.                    */
    gcFinish = 2, /*!< Garbage collector is finished.                 */
    gcLast   = 3, /*!< Garbage collector is tarminating on JVM death. */
} TGCState;


/* Variable for CMS collector state. */

/*!
 * \brief CMS collector is idling.
 */
#define CMS_IDLING 2

/*!
 * \brief CMS collector is initial-marking phase.
 */
#define CMS_INITIALMARKING 3

/*!
 * \brief CMS collector is marking phase.
 */
#define CMS_MARKING 4

/*!
 * \brief CMS collector is final-making phase.
 */
#define CMS_FINALMARKING 7

/*!
 * \brief CMS collector is sweep phase.
 */
#define CMS_SWEEPING 8


/*!
 * \brief This structure is expressing java heap object type.
 */
typedef enum{
    otIllegal    = 0, /*!< The Object is unknown class type.    */
    otInstance   = 1, /*!< The Object is object instance class. */
    otArray      = 2, /*!< The Object is single array class.    */
    otObjArarry  = 3, /*!< The Object is object array class.    */
    otArrayArray = 4, /*!< The Object is multi array class.     */
} TOopType;

/*!
 * \brief This structure is inner "OopMapBlock" class stub.<br/>
 *        This struct is used by get following class information.
 * \sa hotspot/src/share/vm/oops/instanceKlass.hpp
 */
typedef struct{
    int offset;         /*!< Byte offset of the first oop mapped. */
    unsigned int count; /*!< Count of oops mapped in this block.  */
} TOopMapBlock;

/* Macro. */

/*!
 * \brief Convert to THookFunctionInfo macro.
 */
#define HOOK_FUNC(clsSym, funcSym, befFunc, aftFunc) \
    {(clsSym), NULL, (funcSym), (befFunc), NULL, (aftFunc), false}

/*!
 * \brief Enf flag for THookFunctionInfo macro.
 */
#define HOOK_FUNC_END \
    {NULL, NULL, NULL, NULL, NULL, NULL, false}

/* Variables. */

/* Define JVM paramter pointer variable for calling from external. */

/*!
 * \brief Value of "-XX:UseCompressedOops" or "-XX:UseCompressedClassPointers".
 */
extern "C" bool isCOOP;

/*!
 * \brief Value of "-XX:UseParallelGC".
 */
extern "C" bool useParallel;

/*!
 * \brief Value of "-XX:UseParallelOldGC".
 */
extern "C" bool useParOld;

/*!
 * \brief Value of "-XX:UseConcMarkSweepGC".
 */
extern "C" bool useCMS;

/*!
 * \brief Value of "-XX:UseG1GC".
 */
extern "C" bool useG1;

/*!
 * \brief CMS collector state pointer.
 * \sa concurrentMarkSweepGeneration.hpp<br>
 *     at hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/<br>
 *     enum CollectorState
 */
extern int *CMS_collectorState;


/*!
 * \brief JVM safepoint state pointer.
 */
extern "C" int *safePointState;

/* Define CMS GC pointer variable for calling from external. */

/* Define function pointer variable for calling from external. */

/*!
 * \brief Function pointer for "is_in_permanent".
 */
extern "C" THeap_IsInPermanent is_in_permanent;

/*!
 * \brief Pointer of "_collectedHeap" field in Universe.<br>
 *        Use to calling "is_in_permanent" function.
 */
extern "C" void *collectedHeap;

/*!
 * \brief Function pointer for "JvmtiEnv::GetObjectSize".
 */
extern "C" TJvmtiEnv_GetObjectSize getObjectSize;

/*!
 * \brief Function pointer for "java_lang_Class::as_klassOop".
 */
extern "C" TJavaLangClass_AsKlassOop asKlassOop;

/*!
 * \brief Symbol finder object about "libjvm.so" shared library.
 */
extern TSymbolFinder *symFinder;

/*!
 * \brief JVM inner structure scanner.
 */
extern TVMStructScanner *vmScanner;

/*!
 * \brief Bitmap object for G1 GC.
 */
extern TBitMapMarker *checkObjectMap;

/*!
 * \brief VTable list which should be hooked.
 */
extern void *VTableForTypeArrayOopClosure[];


/* Variable for function override. */

/*!
 * \brief Pointer of hook information on parallelGC.
 */
extern "C" THookFunctionInfo *par_hook;

/*!
 * \brief Pointer of hook information on parallelOldGC.
 */
extern "C" THookFunctionInfo *parOld_hook;

/*!
 * \brief Pointer of hook information on CMSGC.
 */
extern "C" THookFunctionInfo *cms_sweep_hook;

/*!
 * \brief Pointer of hook information on CMSGC.
 */
extern "C" THookFunctionInfo *cms_new_hook;

/*!
 * \brief Pointer of hook information on G1GC.
 */
extern "C" THookFunctionInfo *g1_hook;

/*!
 * \brief Pointer of hook information on G1GC event.
 */
extern "C" THookFunctionInfo *g1Event_hook;

/*!
 * \brief Pointer of hook change and adjust oop with GC.
 */
extern "C" THookFunctionInfo *adj_hook;

/*!
 * \brief Pointer of hook oop iterate with JVMTI HeapOverIterate.
 */
extern "C" THookFunctionInfo *jvmti_hook;

/*!
 * \brief Pointer of hook inner GC function.
 */
extern "C" THookFunctionInfo *innerStart_hook;

/*!
 * \brief Flag of JVM is applyed JDK-6964458.<br>
 *        Reimplement class meta-data storage to use native memory.
 *        (PermGen Removal)
 * \sa https://bugs.openjdk.java.net/browse/JDK-6964458
 * \sa http://hg.openjdk.java.net/hsx/hotspot-rt-gate/hotspot/rev/da91efe96a93
 */
extern bool enableCR6964458;

/* Function. */

/* Function for callback. */

/*!
 * \brief Callback function for parallel GC and user's GC.<br>
 *        E.g. System.gc() in java code, JVMTI and etc..
 * \param oop [in] Java heap object(OopDesc format).
 * \warning Param "oop" isn't usable for JVMTI and JNI.
 */
extern "C" void callbackForParallel(void *oop);

/*!
 * \brief Callback function for parallel Old GC.
 * \param oop [in] Java heap object(OopDesc format).
 * \warning Param "oop" isn't usable for JVMTI and JNI.
 */
extern "C" void callbackForParOld(void *oop);

/*!
 * \brief Callback function for OopClosure::do_oop(oop *).<br>
 *        This function is targeted for G1ParScanAndMarkExtRootClosure.
 *        (initial-mark for G1)
 * \param oop [in] Java heap object(OopDesc format).
 */
extern "C" void callbackForDoOop(void **oop);

/*!
 * \brief Callback function for OopClosure::do_oop(narrowOop *).<br>
 *        This function is targeted for G1ParScanAndMarkExtRootClosure.
 *        (initial-mark for G1)
 * \param oop [in] Java heap object(OopDesc format).
 */
extern "C" void callbackForDoNarrowOop(unsigned int *narrowOop);

/*!
 * \brief Callback function for CMS GC and G1 GC.<br>
 *        This function is targeted for Young Gen only.
 * \param oop [in] Java heap object(OopDesc format).
 * \warning Param "oop" isn't usable for JVMTI and JNI.
 * \sa CMSParRemarkTask::do_young_space_rescan()<br>
 *     ContiguousSpace::par_oop_iterate()
 */
extern "C" void callbackForIterate(void *oop);

/*!
 * \brief Callback function for CMS sweep.<br>
 *        This function is targeted for CMS Gen only.
 * \param oop [in] Java heap object(OopDesc format).
 * \warning Param "oop" isn't usable for JVMTI and JNI.
 */
extern "C" void callbackForSweep(void *oop);

/*!
 * \brief Callback function for oop_adjust_pointers.
 * \param oop [in] Java heap object(OopDesc format).
 * \warning Param "oop" isn't usable for JVMTI and JNI.
 */
extern "C" void callbackForAdjustPtr(void *oop);

/*!
 * \brief Callback function for do_addr.
 * \param oop [in] Java heap object(OopDesc format).
 * \warning Param "oop" isn't usable for JVMTI and JNI.
 */
extern "C" void callbackForDoAddr(void *oop);

/*!
 * \brief Callback function for oop_update_pointers.
 * \param oop [in] Java heap object(OopDesc format).
 * \warning Param "oop" isn't usable for JVMTI and JNI.
 */
extern "C" void callbackForUpdatePtr(void *oop);

/*!
 * \brief Callback function for snapshot with data dump or interval.
 * \param oop [in] Java heap object(OopDesc format).
 * \warning Param "oop" isn't usable for JVMTI and JNI.
 */
extern "C" void callbackForJvmtiIterate(void *oop);

/*!
 * \brief Callback function for before G1 GC cleanup.
 */
extern "C" void callbackForG1Cleanup(void);

/*!
 * \brief Callback function for before System.gc() on using G1GC.
 * \param isFull [in] Is this event FullGC?
 */
extern "C" void callbackForG1Full(bool isFull);

/*!
 * \brief Callback function for after System.gc() on using G1GC.
 * \param isFull [in] Is this event FullGC?
 */
extern "C" void callbackForG1FullReturn(bool isFull);

/*!
 * \brief Callback function for WatcherThread.
 */
extern "C" void callbackForWatcherThreadRun(void);


/* Function for init/final. */

/*!
 * \brief Initialization of this util.
 * \param jvmti [in] JVMTI environment object.
 * \return Process result.
 */
bool oopUtilInitialize(jvmtiEnv *jvmti);

/*!
 * \brief Finailization of this util.
 */
void oopUtilFinalize(void);

/*!
 * \brief Setup hooking.
 * \warning Please this function call at after Agent_OnLoad.
 * \param funcOnGC     [in] Pointer of GC callback function.
 * \param funcOnCMS    [in] Pointer of CMSGC callback function.
 * \param funcOnJVMTI  [in] Pointer of JVMTI callback function.
 * \param funcOnAdjust [in] Pointer of adjust class callback function.
 * \param funcOnG1GC   [in] Pointer of event callback on G1GC finished.
 * \param maxMemSize   [in] Allocatable maximum memory size of JVM.
 * \return Process result.
 */
bool setupHook(THeapObjectCallback funcOnGC, THeapObjectCallback funcOnCMS,
    THeapObjectCallback funcOnJVMTI, TKlassAdjustCallback funcOnAdjust,
    TCommonCallback funcOnG1GC, size_t maxMemSize);

/* Function for oop util. */

/*!
 * \brief Getting oop's class information(It's "Klass", not "KlassOop").
 * \param klassOop [in] Java heap object(Inner "KlassOop" class).
 * \return Class information object(Inner "Klass" class).
 */
void *getKlassFromKlassOop(void *klassOop);

/*!
 * \brief Getting oop's class information(It's "Klass", not "KlassOop").
 * \param oop [in] Java heap object(Inner class format).
 * \return Class information object.
 * \sa oopDesc::klass()<br>
 *     at hotspot/src/share/vm/oops/oop.inline.hpp in JDK.
 */
void *getKlassOopFromOop(void *oop);

/*!
 * \brief Getting class's name form java inner class.
 * \param klass [in] Java class object(Inner class format).
 * \return String of object class name.<br>
 *         Don't forget deallocate if value isn't null.
 */
char *getClassName(void *klass);

/*!
 * \brief Get class loader that loaded expected class as KlassOop.
 * \param klassName [in] String of target class name (JNI class format).
 * \return Java heap object which is class loader load expected the class.
 */
TOopType getClassType(const char* klassName);

/*!
 * \brief Get class loader that loaded expected class as KlassOop.
 * \param klassOop [in] Class information object(Inner "Klass" class).
 * \param type     [in] KlassOop type.
 * \return Java heap object which is class loader load expected the class.
 */
void *getClassLoader(void *klassOop, const TOopType type);

/*!
 * \brief Generate oop field offset cache.
 * \param klassOop [in]  Target class object(klassOop format).
 * \param oopType  [in]  Type of inner "Klass" type.
 * \param offsets  [out] Field offset array.<br />
 *                       Please don't forget deallocate this value.
 * \param count    [out] Count of field offset array.
 */
void generateIterateFieldOffsets(void *klassOop, TOopType oopType,
    TOopMapBlock **offsets, int *count);

/*!
 * \brief Iterate oop's field oops.
 * \param event       [in]     Callback function.
 * \param oop         [in]     Itearate target object(OopDesc format).
 * \param oopType     [in]     Type of oop's class.
 * \param ofsData     [in,out] Cache data for iterate oop fields.<br />
 *                             If value is null, then create and set cache data.
 * \param ofsDataSize [in,out] Cache data count.<br />
 *                             If value is null, then set count of "ofsData".
 * \param data        [in,out] User expected data for callback.
 */
void iterateFieldObject(THeapObjectCallback event, void *oop, TOopType oopType,
    TOopMapBlock **ofsData, int *ofsDataSize, void* data);

/* Function for other. */

/*!
 * \brief Setting GC hooking enable.
 * \param enable [in] Is GC hook enable.
 * \return Process result.
 */
bool setGCHookState(bool enable);

/*!
 * \brief Setting JVMTI hooking enable.
 * \param enable [in] Is JVMTI hook enable.
 * \return Process result.
 */
bool setJvmtiHookState(bool enable);

/*!
 * \brief Check CMS garbage collector state.
 * \param state        [in]  State of CMS garbage collector.
 * \param needSnapShot [out] Is need snapshot now.
 * \return CMS collector state.
 * \warning Please don't forget call on JVM death.
 */
int checkCMSState(TGCState state, bool *needSnapShot);

/*!
 * \brief Setup hooking for inner GC event.
 * \warning Please this function call at after Agent_OnLoad.
 * \param enableHook     [in] Flag of enable hooking to function.
 * \param interruptEvent [in] Event callback on many times GC interupt.
 * \return Process result.
 */
bool setupHookForInnerGCEvent(bool enableHook, TCommonCallback interruptEvent);

/*!
 * \brief Get safepoint state.
 * \return Is synchronizing or working at safepoint now.
 */
inline bool isAtSafepoint(void) {
    return (*safePointState == 2);
}

/*!
 * \brief Get oop field exists.
 * \return Does oop have oop field.
 */
inline bool hasOopField(const TOopType oopType) {
    return (oopType == otInstance || oopType == otObjArarry);
}

#endif // _OOP_UTIL_H