Mercurial > hg > release > heapstats-1.0
view agent/src/oopUtil.cpp @ 26:fa4bbeb769a3
Bug 1600: Adapt to JDK-8015107
reviewed-by: ykubota
author | Yasumasa Suenaga <suenaga.yasumasa@lab.ntt.co.jp> |
---|---|
date | Mon, 11 Nov 2013 18:02:40 +0900 |
parents | e20b4494bc92 |
children | 24f77b8a62fe |
line wrap: on
line source
/*! * \file oopUtil.cpp * \brief This file is used to getting information inner JVM.<br> * Copyright (C) 2011-2013 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. * */ #include <jni.h> #include <jvmti.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <sys/types.h> #include <pthread.h> #include <sys/mman.h> #include <unistd.h> #include "oopUtil.hpp" #include "util.hpp" #include "bitMapMarker.hpp" #include "snapShotMain.hpp" #include "libmain.hpp" /* Macros for override functions */ #define DEFINE_OVERRIDE_FUNC_1(prefix) \ extern "C" void *prefix##_override_func_0; #define DEFINE_OVERRIDE_FUNC_2(prefix) \ DEFINE_OVERRIDE_FUNC_1(prefix) \ extern "C" void *prefix##_override_func_1; #define DEFINE_OVERRIDE_FUNC_3(prefix) \ DEFINE_OVERRIDE_FUNC_2(prefix) \ extern "C" void *prefix##_override_func_2; #define DEFINE_OVERRIDE_FUNC_4(prefix) \ DEFINE_OVERRIDE_FUNC_3(prefix) \ extern "C" void *prefix##_override_func_3; #define DEFINE_OVERRIDE_FUNC_8(prefix) \ DEFINE_OVERRIDE_FUNC_4(prefix) \ extern "C" void *prefix##_override_func_4; \ extern "C" void *prefix##_override_func_5; \ extern "C" void *prefix##_override_func_6; \ extern "C" void *prefix##_override_func_7; #define DEFINE_OVERRIDE_FUNC_9(prefix) \ DEFINE_OVERRIDE_FUNC_8(prefix) \ extern "C" void *prefix##_override_func_8; /* Function define. */ /* Override functions. */ /* These functions is defined in override.S. */ /*! * \brief Override function for instance object on parallelGC. */ DEFINE_OVERRIDE_FUNC_4(par) /*! * \brief Override function for instance object on parallelGC for after CR6964458. */ DEFINE_OVERRIDE_FUNC_4(CR6964458_par) /*! * \brief Override function for instance object on parallelGC for after CR8000213. */ DEFINE_OVERRIDE_FUNC_4(CR8000213_par) /*! * \brief Override function for instance object on parallelOldGC. */ DEFINE_OVERRIDE_FUNC_4(parOld) /*! * \brief Override function for instance object on parallelOldGC for after CR6964458. */ DEFINE_OVERRIDE_FUNC_4(CR6964458_parOld) /*! * \brief Override function for instance object on parallelOldGC for after CR8000213. */ DEFINE_OVERRIDE_FUNC_4(CR8000213_parOld) /*! * \brief Override function for sweep at old gen on CMSGC. */ DEFINE_OVERRIDE_FUNC_1(cms_sweep) /*! * \brief Override function for instance object at new gen on CMSGC. */ DEFINE_OVERRIDE_FUNC_4(cms_new) /*! * \brief Override function for instance object at new gen on CMSGC for after CR6964458. */ DEFINE_OVERRIDE_FUNC_4(CR6964458_cms_new) /*! * \brief Override function for instance object at new gen on CMSGC for after CR8000213. */ DEFINE_OVERRIDE_FUNC_4(CR8000213_cms_new) /*! * \brief Override function for instance object on G1GC. */ DEFINE_OVERRIDE_FUNC_9(g1) /*! * \brief Override function for instance object on G1GC for after CR6964458. */ DEFINE_OVERRIDE_FUNC_9(CR6964458_g1) /*! * \brief Override function for instance object on G1GC for after CR8000213. */ DEFINE_OVERRIDE_FUNC_9(CR8000213_g1) /*! * \brief Override function for cleanup event on G1GC. */ DEFINE_OVERRIDE_FUNC_2(g1Event) /*! * \brief Override function for adjust klassOop. */ DEFINE_OVERRIDE_FUNC_8(adj) /*! * \brief Override function for JVMTI function. */ DEFINE_OVERRIDE_FUNC_1(jvmti) /*! * \brief Override function for inner GC function. */ DEFINE_OVERRIDE_FUNC_3(innerStart) /*! * \brief Override function for WatcherThread. */ DEFINE_OVERRIDE_FUNC_1(watcherThread) /* Macro. */ #define SELECT_HOOK_FUNCS(result, prefix) \ if(jvmInfo->isAfterCR8000213()) \ result = CR8000213_##prefix##_hook; \ else if(jvmInfo->isAfterCR6964458()) \ result = CR6964458_##prefix##_hook; \ else \ result = prefix##_hook; /*! * \brief Symbol of "JvmtiEnv::GetObjectSize" macro. */ #ifdef __x86_64__ #define SYMBOL_GETOBJCTSIZE "_ZN8JvmtiEnv13GetObjectSizeEP8_jobjectPl" #else #define SYMBOL_GETOBJCTSIZE "_ZN8JvmtiEnv13GetObjectSizeEP8_jobjectPx" #endif /* Variable. */ /* Variable for pointer dummy. */ /*! * \brief Dummy zero variable.<br> This variable is always 0. */ int dummyZeroInt = 0; /*! * \brief Dummy false flag.<br> This variable is always false. */ bool dummyFalseFlag = false; /* Define JVM paramter pointer variable for calling from external. */ /*! * \brief Pointer to "-XX:UseCompressedOops". */ #ifdef __LP64__ bool *isCOOP = NULL; #else bool *isCOOP = &dummyFalseFlag; #endif /*! * \brief Pointer to "-XX:UseParallelGC". */ bool *useParallel = NULL; /*! * \brief Pointer to "-XX:UseParallelOldGC". */ bool *useParOld = NULL; /*! * \brief Pointer to "-XX:UseConcMarkSweepGC". */ bool *useCMS = NULL; /*! * \brief Pointer to"-XX:UseG1GC". */ bool *useG1 = NULL; /* Variable for CMS collector state. */ /*! * \brief CMS collector is idling. */ const int CMS_IDLING = 2; /*! * \brief CMS collector is initial-marking phase. */ const int CMS_INITIALMARKING = 3; /*! * \brief CMS collector is marking phase. */ const int CMS_MARKING = 4; /*! * \brief CMS collector is final-making phase. */ const int CMS_FINALMARKING = 7; /*! * \brief CMS collector is sweep phase. */ const int CMS_SWEEPING = 8; /*! * \brief CMS collector state pointer. * \sa concurrentMarkSweepGeneration.hpp<br> * at hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/<br> * enum CollectorState */ int *CMS_collectorState = NULL; /* Define function pointer variable for calling from external. */ /*! * \brief Function pointer for "is_in_permanent". */ THeap_IsInPermanent is_in_permanent = NULL; /*! * \brief Pointer of "_collectedHeap" field in Universe.<br> * Use to calling "is_in_permanent" function. */ void *collectedHeap = NULL; /*! * \brief Function pointer for "JvmtiEnv::GetObjectSize". */ TJvmtiEnv_GetObjectSize getObjectSize = NULL; /*! * \brief Function pointer for "java_lang_Class::as_klassOop". */ TJavaLangClass_AsKlassOop asKlassOop = NULL; /* Variable for inner class size. */ /*! * \brief Size of "oopDesc" class in JVM. */ uint64_t clsSizeOopDesc = 0; /*! * \brief Size of "klassOopDesc" class in JVM. */ uint64_t clsSizeKlassOop = 0; /*! * \brief Size of "narrowOop" class in JVM. */ uint64_t clsSizeNarrowOop = 0; /*! * \brief Size of "arrayOopDesc" class in JVM. */ uint64_t clsSizeArrayOop = 0; /*! * \brief Size of "Klass" class in JVM. */ uint64_t clsSizeKlass = 0; /*! * \brief Size of "instanceKlass" class in JVM. */ uint64_t clsSizeInstanceKlass = 0; /* Variable for inner class field offset. */ /*! * \brief Offset of "oopDesc" class's "_metadata._klass" field. * This field is stored class object when JVM don't using COOP. */ off_t ofsKlassAtOop = -1; /*! * \brief Offset of "oopDesc" class's "_metadata._compressed_klass" field. * This field is stored class object when JVM is using COOP. */ off_t ofsCoopKlassAtOop = -1; /*! * \brief Offset of "oopDesc" class's "_mark" field. * This field is stored bit flags of lock information. */ off_t ofsMarkAtOop = -1; /*! * \brief Offset of "Klass" class's "_name" field. * This field is stored symbol object that designed class name. */ off_t ofsNameAtKlass = -1; /*! * \brief Offset of "Symbol" class's "_length" field. * This field is stored string size of class name. */ off_t ofsLengthAtSymbol = -1; /*! * \brief Offset of "Symbol" class's "_body" field. * This field is stored string of class name. */ off_t ofsBodyAtSymbol = -1; /* Variable for environment information. */ /*! * \brief Pointer of COOP base address. */ ptrdiff_t narrowOffsetBase = 0; /*! * \brief Pointer of COOP shift bits. */ int *narrowOffsetShift = &dummyZeroInt; /*! * \brief Pointer of Klass COOP shift bits. */ int *narrowKlassOffsetShift = &dummyZeroInt; /*! * \brief Pointer of COOP base Klass address. */ ptrdiff_t narrowKlassOffsetBase = 0; /*! * \brief Lock bit mask.<br> * Value of "markOopDesc" class's "lock_mask_in_place" constant field. */ uint64_t lockMaskInPlaceMarkOop = 0; /* Variable for CMS marking bitmap. */ /*! * \brief Pointer of CMS marking bitmap start word. */ void *cmsBitMap_startWord = NULL; /*! * \brief Pointer to shifter of CMS bitmap. */ int *cmsBitMap_shifter = NULL; /*! * \brief Pointer to CMS Marking bitmap start memory address. */ size_t *cmsBitMap_startAddr = NULL; /*! * \brief Size of integer(regular integer register) on now environment.<br> * BitsPerWord is used by CMS GC mark bitmap.<br> * This value is default. At "setupForCMS", read from VMIntConstant. */ int32_t HeapWordSize = #ifdef __LP64__ 8 #else 4 #endif ; /*! * \brief Number of bit to need expressing integer size of "HeapWordSize". * HeapWordSize = 2 ^ LogHeapWordSize.<br> * BitsPerWord is used by CMS GC mark bitmap.<br> * This value is default. At "setupForCMS", read from VMIntConstant. */ int32_t LogHeapWordSize = #ifdef __LP64__ 3 #else 2 #endif ; /*! * \brief It's integer's number to need for expressing 64bit integer * on now environment.<br> * BitsPerWord is used by CMS GC mark bitmap.<br> * This value is default. At "setupForCMS", read from JVM symbol. */ int HeapWordsPerLong = #ifdef __LP64__ 1 #else 2 #endif ; /*! * \brief Number of bit to need expressing a integer register.<br> * LogBitsPerWord = 2 ^ LogBitsPerWord.<br> * BitsPerWord is used by CMS GC mark bitmap.<br> * This value is default. At "setupForCMS", read from JVM symbol. */ int LogBitsPerWord = #ifdef __LP64__ 6 #else 5 #endif ; /*! * \brief Number of bit to expressable max integer by single register * on now environment.<br> * LogBitsPerWord = sizeof(long) * 8.<br> * BitsPerWord is used by CMS GC mark bitmap.<br> * This value is default. At "setupForCMS", read from JVM symbol. */ int BitsPerWord = #ifdef __LP64__ 64 #else 32 #endif ; int BitsPerWordMask; /*! * \brief JVM safepoint state pointer. */ int *safePointState = NULL; /* Variable for class object. */ /*! * \brief Symbol finder object about "libjvm.so" shared library. */ TSymbolFinder *symFinder = NULL; /*! * \brief JVM inner structure scanner. */ TVMStructScanner *vmScanner = NULL; /*! * \brief Bitmap object for G1 GC. */ TBitMapMarker *checkObjectMap = NULL; /* Variable for override information. */ /*! * \brief Pointer of hook information on parallelGC. */ THookFunctionInfo par_hook[] = { HOOK_FUNC("_ZTV13instanceKlass", "_ZN13instanceKlass19oop_follow_contentsEP7oopDesc", &par_override_func_0, NULL), HOOK_FUNC("_ZTV13objArrayKlass", "_ZN13objArrayKlass19oop_follow_contentsEP7oopDesc", &par_override_func_1, NULL), HOOK_FUNC("_ZTV14typeArrayKlass", "_ZN14typeArrayKlass19oop_follow_contentsEP7oopDesc", &par_override_func_2, NULL), HOOK_FUNC("_ZTV16instanceRefKlass", "_ZN16instanceRefKlass19oop_follow_contentsEP7oopDesc", &par_override_func_3, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook information on parallelGC for after CR6964458. */ THookFunctionInfo CR6964458_par_hook[] = { HOOK_FUNC("_ZTV13InstanceKlass", "_ZN13InstanceKlass19oop_follow_contentsEP7oopDesc", &CR6964458_par_override_func_0, NULL), HOOK_FUNC("_ZTV13objArrayKlass", "_ZN13objArrayKlass19oop_follow_contentsEP7oopDesc", &CR6964458_par_override_func_1, NULL), HOOK_FUNC("_ZTV14typeArrayKlass", "_ZN14typeArrayKlass19oop_follow_contentsEP7oopDesc", &CR6964458_par_override_func_2, NULL), HOOK_FUNC("_ZTV16InstanceRefKlass", "_ZN16InstanceRefKlass19oop_follow_contentsEP7oopDesc", &CR6964458_par_override_func_3, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook information on parallelGC for after CR8000213. */ THookFunctionInfo CR8000213_par_hook[] = { HOOK_FUNC("_ZTV13InstanceKlass", "_ZN13InstanceKlass19oop_follow_contentsEP7oopDesc", &CR8000213_par_override_func_0, NULL), HOOK_FUNC("_ZTV13ObjArrayKlass", "_ZN13ObjArrayKlass19oop_follow_contentsEP7oopDesc", &CR8000213_par_override_func_1, NULL), HOOK_FUNC("_ZTV14TypeArrayKlass", "_ZN14TypeArrayKlass19oop_follow_contentsEP7oopDesc", &CR8000213_par_override_func_2, NULL), HOOK_FUNC("_ZTV16InstanceRefKlass", "_ZN16InstanceRefKlass19oop_follow_contentsEP7oopDesc", &CR8000213_par_override_func_3, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook information on parallelOldGC. */ THookFunctionInfo parOld_hook[] = { HOOK_FUNC("_ZTV13instanceKlass", "_ZN13instanceKlass19oop_follow_contents" "EP20ParCompactionManagerP7oopDesc", &parOld_override_func_0, NULL), HOOK_FUNC("_ZTV13objArrayKlass", "_ZN13objArrayKlass19oop_follow_contents" "EP20ParCompactionManagerP7oopDesc", &parOld_override_func_1, NULL), HOOK_FUNC("_ZTV14typeArrayKlass", "_ZN14typeArrayKlass19oop_follow_contents" "EP20ParCompactionManagerP7oopDesc", &parOld_override_func_2, NULL), HOOK_FUNC("_ZTV16instanceRefKlass", "_ZN16instanceRefKlass19oop_follow_contents" "EP20ParCompactionManagerP7oopDesc", &parOld_override_func_3, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook information on parallelOldGC for after CR6964458. */ THookFunctionInfo CR6964458_parOld_hook[] = { HOOK_FUNC("_ZTV13InstanceKlass", "_ZN13InstanceKlass19oop_follow_contents" "EP20ParCompactionManagerP7oopDesc", &CR6964458_parOld_override_func_0, NULL), HOOK_FUNC("_ZTV13objArrayKlass", "_ZN13objArrayKlass19oop_follow_contents" "EP20ParCompactionManagerP7oopDesc", &CR6964458_parOld_override_func_1, NULL), HOOK_FUNC("_ZTV14typeArrayKlass", "_ZN14typeArrayKlass19oop_follow_contents" "EP20ParCompactionManagerP7oopDesc", &CR6964458_parOld_override_func_2, NULL), HOOK_FUNC("_ZTV16InstanceRefKlass", "_ZN16InstanceRefKlass19oop_follow_contents" "EP20ParCompactionManagerP7oopDesc", &CR6964458_parOld_override_func_3, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook information on parallelOldGC for after CR8000213. */ THookFunctionInfo CR8000213_parOld_hook[] = { HOOK_FUNC("_ZTV13InstanceKlass", "_ZN13InstanceKlass19oop_follow_contents" "EP20ParCompactionManagerP7oopDesc", &CR8000213_parOld_override_func_0, NULL), HOOK_FUNC("_ZTV13ObjArrayKlass", "_ZN13ObjArrayKlass19oop_follow_contents" "EP20ParCompactionManagerP7oopDesc", &CR8000213_parOld_override_func_1, NULL), HOOK_FUNC("_ZTV14TypeArrayKlass", "_ZN14TypeArrayKlass19oop_follow_contents" "EP20ParCompactionManagerP7oopDesc", &CR8000213_parOld_override_func_2, NULL), HOOK_FUNC("_ZTV16InstanceRefKlass", "_ZN16InstanceRefKlass19oop_follow_contents" "EP20ParCompactionManagerP7oopDesc", &CR8000213_parOld_override_func_3, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook information on CMSGC. */ THookFunctionInfo cms_sweep_hook[] = { HOOK_FUNC("_ZTV12SweepClosure", "_ZN12SweepClosure14do_blk_carefulEP8HeapWord", &cms_sweep_override_func_0, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook information on CMSGC. */ THookFunctionInfo cms_new_hook[] = { HOOK_FUNC("_ZTV13instanceKlass", "_ZN13instanceKlass18oop_oop_iterate_nv" "EP7oopDescP30Par_MarkRefsIntoAndScanClosure", &cms_new_override_func_0, NULL), HOOK_FUNC("_ZTV13objArrayKlass", "_ZN13objArrayKlass18oop_oop_iterate_nv" "EP7oopDescP30Par_MarkRefsIntoAndScanClosure", &cms_new_override_func_1, NULL), HOOK_FUNC("_ZTV14typeArrayKlass", "_ZN14typeArrayKlass15oop_oop_iterate" "EP7oopDescP10OopClosure", &cms_new_override_func_2, NULL), HOOK_FUNC("_ZTV16instanceRefKlass", "_ZN16instanceRefKlass18oop_oop_iterate_nv" "EP7oopDescP30Par_MarkRefsIntoAndScanClosure", &cms_new_override_func_3, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook information on CMSGC for after CR6964458. */ THookFunctionInfo CR6964458_cms_new_hook[] = { HOOK_FUNC("_ZTV13InstanceKlass", "_ZN13InstanceKlass18oop_oop_iterate_nv" "EP7oopDescP30Par_MarkRefsIntoAndScanClosure", &CR6964458_cms_new_override_func_0, NULL), HOOK_FUNC("_ZTV13objArrayKlass", "_ZN13objArrayKlass18oop_oop_iterate_nv" "EP7oopDescP30Par_MarkRefsIntoAndScanClosure", &CR6964458_cms_new_override_func_1, NULL), HOOK_FUNC("_ZTV14typeArrayKlass", "_ZN14typeArrayKlass15oop_oop_iterate" "EP7oopDescP18ExtendedOopClosure", &CR6964458_cms_new_override_func_2, NULL), HOOK_FUNC("_ZTV16InstanceRefKlass", "_ZN16InstanceRefKlass18oop_oop_iterate_nv" "EP7oopDescP30Par_MarkRefsIntoAndScanClosure", &CR6964458_cms_new_override_func_3, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook information on CMSGC for after CR8000213. */ THookFunctionInfo CR8000213_cms_new_hook[] = { HOOK_FUNC("_ZTV13InstanceKlass", "_ZN13InstanceKlass18oop_oop_iterate_nv" "EP7oopDescP30Par_MarkRefsIntoAndScanClosure", &CR8000213_cms_new_override_func_0, NULL), HOOK_FUNC("_ZTV13ObjArrayKlass", "_ZN13ObjArrayKlass18oop_oop_iterate_nv" "EP7oopDescP30Par_MarkRefsIntoAndScanClosure", &CR8000213_cms_new_override_func_1, NULL), HOOK_FUNC("_ZTV14TypeArrayKlass", "_ZN14TypeArrayKlass15oop_oop_iterate" "EP7oopDescP18ExtendedOopClosure", &CR8000213_cms_new_override_func_2, NULL), HOOK_FUNC("_ZTV16InstanceRefKlass", "_ZN16InstanceRefKlass18oop_oop_iterate_nv" "EP7oopDescP30Par_MarkRefsIntoAndScanClosure", &CR8000213_cms_new_override_func_3, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook information on G1GC. */ THookFunctionInfo g1_hook[] = { HOOK_FUNC("_ZTV16G1ParCopyClosureILb0EL9G1Barrier0ELb1EE", "_ZN16G1ParCopyClosureILb0EL9G1Barrier0ELb1EE6do_oopEPP7oopDesc", &g1_override_func_0, NULL), HOOK_FUNC("_ZTV16G1ParCopyClosureILb0EL9G1Barrier0ELb1EE", "_ZN16G1ParCopyClosureILb0EL9G1Barrier0ELb1EE6do_oopEPj", &g1_override_func_1, NULL), HOOK_FUNC("_ZTV13instanceKlass", "_ZN13instanceKlass18oop_oop_iterate_nvEP7oopDescP23G1RootRegionScanClosure", &g1_override_func_2, NULL), HOOK_FUNC("_ZTV13objArrayKlass", "_ZN13objArrayKlass18oop_oop_iterate_nvEP7oopDescP23G1RootRegionScanClosure", &g1_override_func_3, NULL), HOOK_FUNC("_ZTV16instanceRefKlass", "_ZN16instanceRefKlass18oop_oop_iterate_nvEP7oopDescP23G1RootRegionScanClosure", &g1_override_func_4, NULL), HOOK_FUNC("_ZTV13instanceKlass", "_ZN13instanceKlass18oop_oop_iterate_nvEP7oopDescP14G1CMOopClosure", &g1_override_func_5, NULL), HOOK_FUNC("_ZTV13objArrayKlass", "_ZN13objArrayKlass18oop_oop_iterate_nvEP7oopDescP14G1CMOopClosure", &g1_override_func_6, NULL), HOOK_FUNC("_ZTV14typeArrayKlass", "_ZN14typeArrayKlass15oop_oop_iterateEP7oopDescP10OopClosure", &g1_override_func_7, NULL), HOOK_FUNC("_ZTV16instanceRefKlass", "_ZN16instanceRefKlass18oop_oop_iterate_nvEP7oopDescP14G1CMOopClosure", &g1_override_func_8, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook information on G1GC for after CR6964458. */ THookFunctionInfo CR6964458_g1_hook[] = { HOOK_FUNC("_ZTV16G1ParCopyClosureILb0EL9G1Barrier0ELb1EE", "_ZN16G1ParCopyClosureILb0EL9G1Barrier0ELb1EE6do_oopEPP7oopDesc", &CR6964458_g1_override_func_0, NULL), HOOK_FUNC("_ZTV16G1ParCopyClosureILb0EL9G1Barrier0ELb1EE", "_ZN16G1ParCopyClosureILb0EL9G1Barrier0ELb1EE6do_oopEPj", &CR6964458_g1_override_func_1, NULL), HOOK_FUNC("_ZTV13InstanceKlass", "_ZN13InstanceKlass18oop_oop_iterate_nvEP7oopDescP23G1RootRegionScanClosure", &CR6964458_g1_override_func_2, NULL), HOOK_FUNC("_ZTV13objArrayKlass", "_ZN13objArrayKlass18oop_oop_iterate_nvEP7oopDescP23G1RootRegionScanClosure", &CR6964458_g1_override_func_3, NULL), HOOK_FUNC("_ZTV16InstanceRefKlass", "_ZN16InstanceRefKlass18oop_oop_iterate_nvEP7oopDescP23G1RootRegionScanClosure", &CR6964458_g1_override_func_4, NULL), HOOK_FUNC("_ZTV13InstanceKlass", "_ZN13InstanceKlass18oop_oop_iterate_nvEP7oopDescP14G1CMOopClosure", &CR6964458_g1_override_func_5, NULL), HOOK_FUNC("_ZTV13objArrayKlass", "_ZN13objArrayKlass18oop_oop_iterate_nvEP7oopDescP14G1CMOopClosure", &CR6964458_g1_override_func_6, NULL), HOOK_FUNC("_ZTV14typeArrayKlass", "_ZN14typeArrayKlass15oop_oop_iterateEP7oopDescP18ExtendedOopClosure", &CR6964458_g1_override_func_7, NULL), HOOK_FUNC("_ZTV16InstanceRefKlass", "_ZN16InstanceRefKlass18oop_oop_iterate_nvEP7oopDescP14G1CMOopClosure", &CR6964458_g1_override_func_8, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook information on G1GC for after CR8000213. */ THookFunctionInfo CR8000213_g1_hook[] = { HOOK_FUNC("_ZTV16G1ParCopyClosureILb0EL9G1Barrier0ELb1EE", "_ZN16G1ParCopyClosureILb0EL9G1Barrier0ELb1EE6do_oopEPP7oopDesc", &CR8000213_g1_override_func_0, NULL), HOOK_FUNC("_ZTV16G1ParCopyClosureILb0EL9G1Barrier0ELb1EE", "_ZN16G1ParCopyClosureILb0EL9G1Barrier0ELb1EE6do_oopEPj", &CR8000213_g1_override_func_1, NULL), HOOK_FUNC("_ZTV13InstanceKlass", "_ZN13InstanceKlass18oop_oop_iterate_nvEP7oopDescP23G1RootRegionScanClosure", &CR8000213_g1_override_func_2, NULL), HOOK_FUNC("_ZTV13ObjArrayKlass", "_ZN13ObjArrayKlass18oop_oop_iterate_nvEP7oopDescP23G1RootRegionScanClosure", &CR8000213_g1_override_func_3, NULL), HOOK_FUNC("_ZTV16InstanceRefKlass", "_ZN16InstanceRefKlass18oop_oop_iterate_nvEP7oopDescP23G1RootRegionScanClosure", &CR8000213_g1_override_func_4, NULL), HOOK_FUNC("_ZTV13InstanceKlass", "_ZN13InstanceKlass18oop_oop_iterate_nvEP7oopDescP14G1CMOopClosure", &CR8000213_g1_override_func_5, NULL), HOOK_FUNC("_ZTV13ObjArrayKlass", "_ZN13ObjArrayKlass18oop_oop_iterate_nvEP7oopDescP14G1CMOopClosure", &CR8000213_g1_override_func_6, NULL), HOOK_FUNC("_ZTV14TypeArrayKlass", "_ZN14TypeArrayKlass15oop_oop_iterateEP7oopDescP18ExtendedOopClosure", &CR8000213_g1_override_func_7, NULL), HOOK_FUNC("_ZTV16InstanceRefKlass", "_ZN16InstanceRefKlass18oop_oop_iterate_nvEP7oopDescP14G1CMOopClosure", &CR8000213_g1_override_func_8, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook information on G1GC cleanup event. */ THookFunctionInfo g1Event_hook[] = { HOOK_FUNC("_ZTV9CMCleanUp", "_ZN9CMCleanUp7do_voidEv", &g1Event_override_func_0, NULL), HOOK_FUNC("_ZTV16VM_G1CollectFull", "_ZN16VM_G1CollectFull4doitEv", &g1Event_override_func_1, (void*)&callbackForG1FullReturn), HOOK_FUNC_END }; /*! * \brief Pointer of hook change and adjust oop with GC. */ THookFunctionInfo adj_hook[] = { HOOK_FUNC("_ZTV18instanceKlassKlass", "_ZN18instanceKlassKlass19oop_adjust_pointersEP7oopDesc", &adj_override_func_0, NULL), HOOK_FUNC("_ZTV18objArrayKlassKlass", "_ZN18objArrayKlassKlass19oop_adjust_pointersEP7oopDesc", &adj_override_func_1, NULL), HOOK_FUNC("_ZTV15arrayKlassKlass", "_ZN15arrayKlassKlass19oop_adjust_pointersEP7oopDesc", &adj_override_func_2, NULL), HOOK_FUNC("_ZTV20MoveAndUpdateClosure", #ifdef __LP64__ "_ZN20MoveAndUpdateClosure7do_addrEP8HeapWordm", #else "_ZN20MoveAndUpdateClosure7do_addrEP8HeapWordj", #endif &adj_override_func_3, NULL), HOOK_FUNC("_ZTV17UpdateOnlyClosure", #ifdef __LP64__ "_ZN17UpdateOnlyClosure7do_addrEP8HeapWordm", #else "_ZN17UpdateOnlyClosure7do_addrEP8HeapWordj", #endif &adj_override_func_4, NULL), HOOK_FUNC("_ZTV18instanceKlassKlass", "_ZN18instanceKlassKlass19oop_update_pointers" "EP20ParCompactionManagerP7oopDesc", &adj_override_func_5, NULL), HOOK_FUNC("_ZTV18objArrayKlassKlass", "_ZN18objArrayKlassKlass19oop_update_pointers" "EP20ParCompactionManagerP7oopDesc", &adj_override_func_6, NULL), HOOK_FUNC("_ZTV15arrayKlassKlass", "_ZN15arrayKlassKlass19oop_update_pointers" "EP20ParCompactionManagerP7oopDesc", &adj_override_func_7, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook oop iterate with JVMTI HeapOverIterate. */ THookFunctionInfo jvmti_hook[] = { HOOK_FUNC("_ZTV28IterateOverHeapObjectClosure", "_ZN28IterateOverHeapObjectClosure9do_objectEP7oopDesc", &jvmti_override_func_0, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook inner GC function for default. */ THookFunctionInfo innerStart_hook[] = { HOOK_FUNC("_ZTV20ParallelScavengeHeap", "_ZN20ParallelScavengeHeap31accumulate_statistics_all_tlabsEv", &innerStart_override_func_0, NULL), HOOK_FUNC("_ZTV13CollectedHeap", "_ZN13CollectedHeap31accumulate_statistics_all_tlabsEv", &innerStart_override_func_1, NULL), HOOK_FUNC("_ZTV16GenCollectedHeap", "_ZN16GenCollectedHeap11gc_prologueEb", &innerStart_override_func_2, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of WatcherThread hook. */ THookFunctionInfo watcherThread_hook[] = { HOOK_FUNC("_ZTV13WatcherThread", "_ZN13WatcherThread3runEv", &watcherThread_override_func_0, (void *)callbackForWatcherThreadRun), HOOK_FUNC_END }; /* Event callback for outter. */ /*! * \brief Callback function for GC function hooking. */ THeapObjectCallback gcCallbackFunc = NULL; /*! * \brief Callback function for JVMTI iterate hooking. */ THeapObjectCallback jvmtiIteCallbackFunc = NULL; /*! * \brief Callback function for adjust oop function hooking. */ TKlassAdjustCallback adjustCallbackFunc = NULL; /*! * \brief Callback function for finished G1GC. */ TCommonCallback g1FinishCallbackFunc = NULL; /*! * \brief Callback function for interrupt GC. */ TCommonCallback gcInterruptCallbackFunc = NULL; /* Variable for inner work. */ /*! * \brief flag of snapshot with CMS phase. */ bool needSnapShotByCMSPhase = false; /*! * \brief flag of GC hooking enable. */ bool isEnableGCHooking = false; /*! * \brief flag of JVMTI hooking enable. */ bool isEnableJvmtiHooking = false; /*! * \brief Pthread key to store old klassOop. */ pthread_key_t oldKlassOopKey; /*! * \brief flag of inner GC function is called many times. */ bool isInvokeGCManyTimes = false; /*! * \brief VTable list which should be hooked. */ void *VTableForTypeArrayOopClosure[2] __attribute__((aligned(16))); /* Function. */ /* Function for utilities. */ /*! * \brief Convert COOP(narrowOop) to wide Oop(normally Oop). * \param narrowOop [in] Java heap object(compressed format Oop). * \return Wide OopDesc object. */ inline void *getWideOop(unsigned int narrowOop) { /* * narrow oop decoding is defined in * inline oop oopDesc::decode_heap_oop_not_null(narrowOop v) * hotspot/src/share/vm/oops/oop.inline.hpp */ return (void*)(narrowOffsetBase + ((ptrdiff_t)narrowOop << (*narrowOffsetShift))); } /*! * \brief Convert COOP(narrowKlass) to wide Klass(normally Klass). * \param narrowKlass [in] Java Klass object(compressed Klass pointer). * \return Wide Klass object. */ inline void *getWideKlass(unsigned int narrowKlass) { /* * narrowKlass decoding is defined in * inline Klass* Klass::decode_klass_not_null(narrowKlass v) * hotspot/src/share/vm/oops/klass.inline.hpp */ return (void*)(narrowKlassOffsetBase + ((ptrdiff_t)narrowKlass << (*narrowKlassOffsetShift))); } /*! * \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) { if(klassOop == NULL){ return NULL; } else if(jvmInfo->isAfterCR6964458()){ return klassOop; } else{ return incAddress(klassOop, clsSizeKlassOop); } } /*! * \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) { void *tempAddr = NULL; /* Sanity check. */ if (unlikely(oop == NULL)) { return NULL; } /* If JVM use "C"ompressed "OOP". */ if (*isCOOP) { /* Get oop's klassOop from "_compressed_klass" field. */ unsigned int* testAddr = (unsigned int*)((ptrdiff_t)oop + ofsCoopKlassAtOop); if (likely(testAddr != NULL)) { /* Decode COOP. */ tempAddr = getWideKlass(*testAddr); } } else { /* Get oop's klassOop from "_klass" field. */ void **testAddr = (void**)incAddress(oop, ofsKlassAtOop); if (likely(testAddr != NULL)) { tempAddr = (*testAddr); } } return tempAddr; } /*! * \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) { /* Sanity check. */ if (unlikely(klass == NULL)) { return NULL; } /* Get class symbol information. */ void **klassSymbol = (void**)incAddress(klass, ofsNameAtKlass); if (unlikely(klassSymbol == NULL || (*klassSymbol) == NULL)) { return NULL; } /* Get class name pointer. */ char *name = (char*)incAddress((*klassSymbol), ofsBodyAtSymbol); if (unlikely(name == NULL)) { return NULL; } bool isInstanceClass = (*name != '['); /* Get class name size. */ unsigned short len = *(unsigned short*) incAddress((*klassSymbol), ofsLengthAtSymbol); char *str = NULL; /* If class is instance class. */ if (isInstanceClass) { /* Add length of "L" and ";". */ str = (char*)malloc(len + 3); } else { /* Get string memory. */ str = (char*)malloc(len + 1); } if (likely(str != NULL)) { /* Get class name. */ if (isInstanceClass) { /* Copy class name if class is instance class. */ /* As like "instanceKlass::signature_name()". */ str[0] = 'L'; //memcpy(&str[1], name, len); __builtin_memcpy(&str[1], name, len); str[len + 1] = ';'; str[len + 2] = '\0'; } else { /* Copy class name if class is other. */ //memcpy(str, name, len); __builtin_memcpy(str, name, len); str[len] = '\0'; } } return str; } /*! * \brief Get oop forward address. * \param oop [in] Java heap object. * \return Wide OopDesc object. */ inline void *getForwardAddr(void *oop) { /* Sanity check. */ if (unlikely(oop == NULL)) { return NULL; } /* Get OopDesc::_mark field. */ ptrdiff_t markOop = *(ptrdiff_t*)incAddress(oop, ofsMarkAtOop); return (void*)(markOop & ~lockMaskInPlaceMarkOop); } /*! * \brief Is marked object on CMS bitmap. * \param oop [in] Java heap object(Inner class format). * \return Value is true, if object is marked. */ inline bool isMarkedObject(void *oop) { size_t idx = (((ptrdiff_t)oop - (ptrdiff_t)cmsBitMap_startWord) >> ((unsigned)LogHeapWordSize + (unsigned)*cmsBitMap_shifter)); size_t mask = (size_t)1 << (idx & BitsPerWordMask); return (((size_t*)cmsBitMap_startAddr)[(idx >> LogBitsPerWord)] & mask) != 0; } /*! * \brief Switching override function enable state. * \param list [in] List of hooking information. * \param enable [in] Enable of override function. * \return Process result. */ bool switchOverrideFunction(THookFunctionInfo *list, bool enable) { /* Variable for list pointer. */ THookFunctionInfo *arr = list; /* Variable for list item count. */ int listCnt = 0; /* Variable for succeed count. */ int doneCnt = 0; /* Search class and function symbol. */ for(; arr->originalFunc != NULL; listCnt++){ /* Variable for store vtable. */ void **vtable = arr->vtable; /* Variable for store function pointer. */ void *targetFunc = NULL; void *destFunc = NULL; /* Setting swap target and swap dest. */ if(enable){ targetFunc = arr->originalFunc; destFunc = arr->overrideFunc; } else{ targetFunc = arr->overrideFunc; destFunc = arr->originalFunc; } if(unlikely(vtable == NULL || targetFunc == NULL || destFunc == NULL)){ /* Skip illegal. */ arr++; continue; } const int VTABLE_SKIP_LIMIT = 1000; for(int i = 0; i < VTABLE_SKIP_LIMIT && *vtable == NULL; i++){ /* Skip null entry. */ vtable++; } while(*vtable != NULL){ /* If target function. */ if(*vtable == targetFunc){ if(unlikely(!arr->isVTableWritable)){ /* Avoid memory protection for vtable * libstdc++ may remove write permission from vtable * http://gcc.gnu.org/ml/gcc-patches/2012-11/txt00001.txt */ ptrdiff_t start_page = (ptrdiff_t)vtable & ~(systemPageSize - 1); ptrdiff_t end_page = ((ptrdiff_t)vtable + sizeof(void *)) & ~(systemPageSize - 1); size_t len = systemPageSize + (end_page - start_page); mprotect((void *)start_page, len, PROT_READ | PROT_WRITE); arr->isVTableWritable = true; } *vtable = destFunc; doneCnt++; break; } /* Move next vtable entry. */ vtable++; } /* Move next list item. */ arr++; } return (listCnt == doneCnt); } /* Function for callback. */ /*! * \brief Callback function for snapshot. * \param oop [in] Java heap object(OopDesc format). * \warning Param "oop" isn't usable for JVMTI and JNI. */ inline void callbackForSnapshot(void *oop) { if (likely(gcCallbackFunc != NULL)) { void *klassOop = NULL; jlong size = 0; /* Get class. */ klassOop = getKlassOopFromOop(oop); /* Get object size. */ if (likely(getObjectSize != NULL)) { getObjectSize(NULL, (jobject)&oop, &size); } /* Invoke callback. */ gcCallbackFunc(klassOop, size); } } /*! * \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) { /* Invoke snapshot callback. */ callbackForSnapshot(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) { /* Invoke snapshot callback. */ callbackForSnapshot(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) { if((oop == NULL) || (*oop == NULL) || is_in_permanent(collectedHeap, *oop)) return; if (checkObjectMap->checkAndMark(*oop)) { /* Object is already collected by G1GC collector. */ return; } /* Invoke snapshot callback. */ callbackForSnapshot(*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) { void *oop = getWideOop(*narrowOop); callbackForDoOop(&oop); } /*! * \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) { if (*useCMS) { /* If object is in CMS gen. */ if ((ptrdiff_t)oop >= (ptrdiff_t)cmsBitMap_startWord) { /* Skip. because collect object in CMS gen by callbackForSweep. */ return; } } else if (*useG1 && checkObjectMap->checkAndMark(oop)) { /* Object is already collected by G1GC collector. */ return; } /* Invoke snapshot callback. */ callbackForSnapshot(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) { /* If object isn't GC target. */ if (likely(isMarkedObject(oop))) { /* Invoke snapshot callback. */ callbackForSnapshot(oop); } } /*! * \brief Callback function for klassOop. * \param oldOop [in] Old java class object. * \param newOop [in] New java class object. * \warning Param "oop" isn't usable for JVMTI and JNI. */ inline void callbackForAdjustKlass(void *oldOop, void *newOop) { if (likely(adjustCallbackFunc != NULL)) { adjustCallbackFunc(oldOop, newOop); } } /*! * \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) { /* Get new class oop. */ void *newOop = getForwardAddr(oop); if (newOop != NULL) { /* Invoke callback. */ callbackForAdjustKlass(oop, newOop); } } /*! * \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) { /* Get store memory. */ void **oldOop = (void**)pthread_getspecific(oldKlassOopKey); if (unlikely(oldOop == NULL)) { /* Allocate and set store memory. */ oldOop = (void**)malloc(sizeof(void*)); pthread_setspecific(oldKlassOopKey, oldOop); } /* Store old klassOop. */ if (likely(oldOop != NULL)) { (*oldOop) = 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) { /* Get old class oop. */ void **oldOop = (void**)pthread_getspecific(oldKlassOopKey); if (likely(oldOop != NULL && (*oldOop) != NULL)) { /* Invoke callback. */ callbackForAdjustKlass(oldOop, oop); /* Cleanup old data. */ (*oldOop) = NULL; } } /*! * \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) { if (likely(jvmtiIteCallbackFunc != NULL)) { void *klassOop = NULL; jlong size = 0; /* Get class name. */ klassOop = getKlassOopFromOop(oop); /* Get object size. */ if (likely(getObjectSize != NULL)) { getObjectSize(NULL, (jobject)&oop, &size); } /* Invoke callback. */ jvmtiIteCallbackFunc(klassOop, size); } } /*! * \brief Callback function for before G1 GC cleanup. */ extern "C" void callbackForG1Cleanup(void) { if (likely(g1FinishCallbackFunc != NULL)) { /* Invoke callback. */ g1FinishCallbackFunc(); } /* Clear bitmap. */ checkObjectMap->clear(); } /*! * \brief Callback function for before System.gc() on using G1GC. */ extern "C" void callbackForG1Full(void) { THookFunctionInfo *funcs; SELECT_HOOK_FUNCS(funcs, g1) /* * Disable G1 callback function: * OopClosure for typeArrayKlass is called by G1 FullCollection. */ switchOverrideFunction(funcs, false); /* Discard existed snapshot data */ snapshotByGC->clear(); checkObjectMap->clear(); } /*! * \brief Callback function for after System.gc() on using G1GC. */ extern "C" void callbackForG1FullReturn(void) { THookFunctionInfo *funcs; SELECT_HOOK_FUNCS(funcs, g1) /* Restore G1 callback. */ switchOverrideFunction(funcs, true); if(likely(g1FinishCallbackFunc != NULL)){ /* Invoke callback. */ g1FinishCallbackFunc(); } /* Clear bitmap. */ checkObjectMap->clear(); } /*! * \brief Callback function for starting inner GC. */ extern "C" void callbackForInnerGCStart(void) { /* If call GC function more one. */ if(unlikely(isInvokeGCManyTimes)){ /* Invoke GC interrupt callback. */ if(likely(gcInterruptCallbackFunc != NULL)){ gcInterruptCallbackFunc(); } } else{ /* Update state. */ isInvokeGCManyTimes = true; } /* Get current GCCause. */ jvmInfo->loadGCCause(); } /*! * \brief Callback function for WatcherThread. */ extern "C" void callbackForWatcherThreadRun(void){ jvmInfo->detectDelayInfoAddress(); } /* Function for pthread. */ /*! * \brief Callback for pthread key destructor. * \param data [in] Data related to pthread key. */ void pThreadKeyDestructor(void *data) { if (likely(data != NULL)) { /* Cleanup allocated memory on "callbackForDoAddr". */ free(data); } } /* Function for init/final. */ /*! * \brief Search common JVM information structures at "OnVMInit". * \return Process result. */ bool searchCommonInformation(void) { /* List of common field offset. */ TOffsetNameMap ofsMap[] = { {"Universe", "_collectedHeap", NULL, &collectedHeap}, {"Universe", "_narrow_oop._base", NULL, (void **)&narrowOffsetBase}, {"Universe", "_narrow_oop._shift", NULL, (void **)&narrowOffsetShift}, {"Universe", "_narrow_klass._base", NULL, (void **)&narrowKlassOffsetBase}, {"Universe", "_narrow_klass._shift", NULL, (void **)&narrowKlassOffsetShift}, {"oopDesc", "_metadata._klass", &ofsKlassAtOop, NULL}, {"oopDesc", "_metadata._compressed_klass", &ofsCoopKlassAtOop, NULL}, {"oopDesc", "_mark", &ofsMarkAtOop, NULL}, {"Klass", "_name", &ofsNameAtKlass, NULL}, /* * See 6990754: * Use native memory and reference counting to implement SymbolTable. * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6990754 * http://hg.openjdk.java.net/hsx/hotspot-rt-gate/hotspot/rev/3582bf76420e */ {"symbolOopDesc", "_length", &ofsLengthAtSymbol, NULL}, {"symbolOopDesc", "_body", &ofsBodyAtSymbol, NULL}, {"Symbol", "_length", &ofsLengthAtSymbol, NULL}, {"Symbol", "_body", &ofsBodyAtSymbol, NULL}, /* End flag. */ {NULL, NULL, NULL, NULL} }; vmScanner->GetDataFromVMStructs(ofsMap); /* If failure getting common field offset information. */ if (unlikely(collectedHeap == NULL || narrowOffsetBase == 0 || narrowOffsetShift == NULL || ofsKlassAtOop == -1 || ofsCoopKlassAtOop == -1 || ofsNameAtKlass == -1 || ofsLengthAtSymbol == -1 || ofsBodyAtSymbol == -1)) { PRINT_WARN_MSG("Failure getting information form JVM." " info:Common from:VMStructs"); return false; } if(!jvmInfo->isAfterCR8003424()){ narrowKlassOffsetBase = narrowOffsetBase; narrowKlassOffsetShift = narrowOffsetShift; } if(!jvmInfo->isAfterCR6964458()){ /* List of common class size. */ TTypeSizeMap typeMap[] = { {"klassOopDesc", &clsSizeKlassOop}, /* End flag. */ {NULL, NULL} }; vmScanner->GetDataFromVMTypes(typeMap); /* If failure getting common class size information. */ if (unlikely(clsSizeKlassOop == 0)) { PRINT_WARN_MSG("Failure getting information form JVM." " info:Common from:VMTypes"); return false; } } /* List of common long constant. */ TLongConstMap longMap[] = { {"markOopDesc::lock_mask_in_place", &lockMaskInPlaceMarkOop}, /* End flag. */ {NULL, NULL} }; vmScanner->GetDataFromVMLongConstants(longMap); /* If failure getting common class size information. */ if (unlikely(lockMaskInPlaceMarkOop == 0)) { PRINT_WARN_MSG("Failure getting information form JVM." " info:Common from:VMLongConstants"); return false; } return true; } /*! * \brief Search common flag. */ void searchCommonFlags(void) { /* Search flag symbols. */ struct { const char *symbolStr; bool** flagPtr; } flagList[] = { #ifdef __LP64__ {"UseCompressedOops", &isCOOP}, #endif {"UseParallelGC", &useParallel}, {"UseParallelOldGC", &useParOld}, {"UseConcMarkSweepGC", &useCMS}, {"UseG1GC", &useG1}, /* End flag. */ {NULL, NULL} }; for (int i = 0; flagList[i].flagPtr != NULL; i++) { bool *tempPtr = NULL; /* Search symbol. */ tempPtr = (bool*)symFinder->findSymbol(flagList[i].symbolStr); /* If not found symbol. */ if (unlikely(tempPtr == NULL)) { PRINT_WARN_MSG_HEADER << "Not found java symbol." << " symbol:\"" << flagList[i].symbolStr << "\"" << NEWLINE; /* Set dummy flag. */ tempPtr = &dummyFalseFlag; } (*flagList[i].flagPtr) = tempPtr; } #ifdef __LP64__ if(jvmInfo->isAfterCR6964458()){ bool *tempPtr = NULL; const char *target_sym = jvmInfo->isAfterCR8015107() ? "UseCompressedClassPointers" : "UseCompressedKlassPointers"; /* Search symbol. */ tempPtr = (bool*)symFinder->findSymbol(target_sym); /* If not found symbol. */ if (unlikely(tempPtr == NULL)) { PRINT_WARN_MSG_HEADER << target_sym << " not found." << NEWLINE; } else{ isCOOP = tempPtr; } } #endif if(*isCOOP){ PRINT_DEBUG_MSG("Compressed Class = true"); } else{ PRINT_DEBUG_MSG("Compressed Class = false"); } if(*useG1){ /* Add vtable offset */ #ifdef __LP64__ VTableForTypeArrayOopClosure[0] = incAddress(symFinder->findSymbol("_ZTV14G1CMOopClosure"), 16); VTableForTypeArrayOopClosure[1] = incAddress(symFinder->findSymbol("_ZTV23G1RootRegionScanClosure"), 16); #else VTableForTypeArrayOopClosure[0] = incAddress(symFinder->findSymbol("_ZTV14G1CMOopClosure"), 8); VTableForTypeArrayOopClosure[1] = incAddress(symFinder->findSymbol("_ZTV23G1RootRegionScanClosure"), 8); #endif } } /*! * \brief Search common function. * \return Process result. */ bool searchCommonFunction(void) { if(jvmInfo->isAfterCR6964458()){ is_in_permanent = &is_in_permanent_AfterCR6964458; } else{ /* Search "is_in_permanent" function symbol. */ if(*useParallel || *useParOld){ is_in_permanent = (THeap_IsInPermanent)symFinder->findSymbol( "_ZNK20ParallelScavengeHeap15is_in_permanentEPKv"); } else{ is_in_permanent = (THeap_IsInPermanent)symFinder->findSymbol( "_ZNK10SharedHeap15is_in_permanentEPKv"); } /* If not found "is_in_permanent" function symbol. */ if(unlikely(is_in_permanent == NULL)){ PRINT_WARN_MSG("Not found java symbol. symbol:\"is_in_permanent\""); return false; } } /* Search "GetObjectSize" function symbol. */ getObjectSize = (TJvmtiEnv_GetObjectSize)symFinder->findSymbol(SYMBOL_GETOBJCTSIZE); /* If not found "GetObjectSize" function symbol. */ if(unlikely(getObjectSize == NULL)){ PRINT_WARN_MSG("Not found java symbol. symbol:\"GetObjectSize\""); return false; } /* Search "as_klassOop" function symbol. */ if(jvmInfo->isAfterCR6964458()){ /* Search "as_Klass" function symbol. */ asKlassOop = (TJavaLangClass_AsKlassOop)symFinder->findSymbol( "_ZN15java_lang_Class8as_KlassEP7oopDesc"); /* If not found "as_klassOop" function symbol. */ if(unlikely(asKlassOop == NULL)){ PRINT_WARN_MSG("Not found java symbol. symbol:\"as_Klass\""); return false; } } else{ /* Search "as_klassOop" function symbol. */ asKlassOop = (TJavaLangClass_AsKlassOop)symFinder->findSymbol( "_ZN15java_lang_Class11as_klassOopEP7oopDesc"); /* If not found "as_klassOop" function symbol. */ if(unlikely(asKlassOop == NULL)){ PRINT_WARN_MSG("Not found java symbol. symbol:\"as_klassOop\""); return false; } } /* Search symbol of variable stored safepoint state. */ safePointState = (int*)symFinder->findSymbol("_ZN20SafepointSynchronize6_stateE"); /* If not found "_state" variable symbol. */ if (unlikely(safePointState == NULL)) { PRINT_WARN_MSG("Not found java symbol. symbol:\"safepoint_state\""); return false; } return true; } /*! * \brief Setup override funtion. * \param list [in] List of hooking information. * \return Process result. */ bool setupOverrideFunction(THookFunctionInfo *list) { /* Variable for list pointer. */ THookFunctionInfo *arr = list; /* Search class and function symbol. */ for (int i = 0; arr->vtableSymbol != NULL; i++) { /* Search class(vtable) symbol. */ arr->vtable = (void**)symFinder->findSymbol(arr->vtableSymbol); if (unlikely(arr->vtable == NULL)) { PRINT_WARN_MSG_HEADER << "Not found java symbol." << " symbol:\"" << arr->vtableSymbol << "\"" << NEWLINE; return false; } /* Search function symbol. */ arr->originalFunc = symFinder->findSymbol(arr->funcSymbol); if (unlikely(arr->originalFunc == NULL)) { PRINT_WARN_MSG_HEADER << "Not found java symbol." << " symbol:\"" << arr->funcSymbol << "\"" << NEWLINE; return false; } /* Move next list item. */ arr++; } return true; } /*! * \brief Setup GC hooking for parallel. * \return Process result. */ bool setupForParallel(void) { THookFunctionInfo *funcs; SELECT_HOOK_FUNCS(funcs, par) /* If failure getting function information. */ if(unlikely(!setupOverrideFunction(funcs))){ PRINT_WARN_MSG("Failure function overriding. func:parallel"); return false; } return true; } /*! * \brief Setup GC hooking for parallel old GC. * \return Process result. */ bool setupForParallelOld(void) { THookFunctionInfo *funcs; SELECT_HOOK_FUNCS(funcs, parOld) /* If failure getting function information. */ if(unlikely(!setupOverrideFunction(funcs))){ PRINT_WARN_MSG("Failure function overriding. func:par_old"); return false; } return true; } /*! * \brief Setup GC hooking for CMSGC. * \return Process result. */ bool setupForCMS(void) { void *cmsCollector = NULL; off_t offsetLowAtVirtualSpace = -1; off_t offsetCmsStartWord = -1; off_t offsetCmsShifter = -1; off_t offsetCmsMapAtCollector = -1; off_t offsetCmsVirtualSpace = -1; TOffsetNameMap ofsMap[] = { {"CMSBitMap", "_virtual_space", &offsetCmsVirtualSpace, NULL}, {"CMSBitMap", "_bmStartWord", &offsetCmsStartWord, NULL}, {"CMSBitMap", "_shifter", &offsetCmsShifter, NULL}, {"CMSCollector", "_markBitMap", &offsetCmsMapAtCollector, NULL}, {"ConcurrentMarkSweepThread", "_collector", NULL, &cmsCollector}, {"VirtualSpace", "_low", &offsetLowAtVirtualSpace, NULL}, /* End flag. */ {NULL, NULL, NULL, NULL} }; vmScanner->GetDataFromVMStructs(ofsMap); /* If failure getting offset. */ if (unlikely(offsetCmsVirtualSpace == -1 || offsetCmsShifter == -1 || offsetCmsMapAtCollector == -1 || cmsCollector == NULL || offsetLowAtVirtualSpace == -1 || *(void**)cmsCollector == NULL)) { PRINT_WARN_MSG("Failure getting information form JVM." " info:CMS from:vmStructs"); return false; } if(jvmInfo->isAfterCR6964458()){ off_t bmWordSizeOfs = -1; TOffsetNameMap bmWordSizeMap[] = { {"CMSBitMap", "_bmWordSize", &bmWordSizeOfs, NULL}, {NULL, NULL, NULL, NULL} }; vmScanner->GetDataFromVMStructs(bmWordSizeMap); if(bmWordSizeOfs == -1){ PRINT_WARN_MSG("Failure getting information form JVM." " info:CMS from:vmStructs"); return false; } /* CMSBitMap::_bmStartWord is appeared before _bmWordSize. * See CMSBitMap definition in * hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp */ offsetCmsStartWord = bmWordSizeOfs - sizeof(void *); } else if(offsetCmsStartWord == -1){ PRINT_WARN_MSG("Failure getting information form JVM." " info:CMS from:vmStructs"); return false; } /* Calculate about CMS bitmap information. */ cmsCollector = *(void**)cmsCollector; ptrdiff_t cmsBitmapPtr = (ptrdiff_t)cmsCollector + offsetCmsMapAtCollector; cmsBitMap_startWord = *(void**)(cmsBitmapPtr + offsetCmsStartWord); cmsBitMap_shifter = (int*)(cmsBitmapPtr + offsetCmsShifter); ptrdiff_t virtSpace = cmsBitmapPtr + offsetCmsVirtualSpace; cmsBitMap_startAddr = *(size_t**)(virtSpace + offsetLowAtVirtualSpace); /* If failure getting CMS bitmap information. */ if (unlikely(cmsBitMap_startWord == NULL || cmsBitMap_shifter == NULL || cmsBitMap_startAddr == NULL)) { PRINT_WARN_MSG("Failure getting information form JVM." " info:CMS from:calculate"); return false; } /* List of integer constant data target. */ TIntConstMap intMap[] = { {"HeapWordSize", &HeapWordSize}, {"LogHeapWordSize", &LogHeapWordSize}, /* End flag. */ {NULL, NULL} }; vmScanner->GetDataFromVMIntConstants(intMap); /* Search symbol for CMS bitmap. */ struct { const char *symbol; const char *subSymbol; int *pointer; } intSymList[] = { {"HeapWordsPerLong", "_ZL16HeapWordsPerLong", &HeapWordsPerLong}, {"LogBitsPerWord", "_ZL14LogBitsPerWord", &LogBitsPerWord}, {"BitsPerWord", "_ZL11BitsPerWord", &BitsPerWord}, /* End flag. */ {NULL, NULL, NULL} }; for (int i = 0; intSymList[i].pointer != NULL; i++) { int *intPos = NULL; intPos = (int*)symFinder->findSymbol(intSymList[i].symbol); /* If not found integer symbol. */ if (unlikely(intPos == NULL)) { intPos = (int*)symFinder->findSymbol(intSymList[i].subSymbol); } /* If not found integer symbol. */ if (unlikely(intPos == NULL)) { PRINT_WARN_MSG_HEADER << "Not found java symbol. Use default value." << " symbol:\"" << intSymList[i].symbol << "\"" << NEWLINE; } else { (*intSymList[i].pointer) = (*intPos); } } /* Search symbol for CMS state. */ CMS_collectorState = (int*)symFinder->findSymbol( "_ZN12CMSCollector15_collectorStateE"); /* If not found "CMS_collectorState" function symbol. */ if (unlikely(CMS_collectorState == NULL)) { PRINT_WARN_MSG("Not found java symbol. symbol:\"CollectorState\""); return false; } THookFunctionInfo *funcs; SELECT_HOOK_FUNCS(funcs, cms_new) /* If failure getting function information. */ if (unlikely(!setupOverrideFunction(funcs))) { PRINT_WARN_MSG("Failure function overriding. func:CMS_new"); return false; } /* If failure getting function information. */ if (unlikely(!setupOverrideFunction(cms_sweep_hook))) { PRINT_WARN_MSG("Failure function overriding. func:CMS_sweep"); return false; } BitsPerWordMask = BitsPerWord - 1; return true; } /*! * \brief Setup GC hooking for G1GC * \return Process result. */ bool setupForG1GC(size_t maxMemSize) { off_t offsetG1Committed = -1; off_t offsetMemRegionStart = -1; TOffsetNameMap ofsMap[] = { {"G1CollectedHeap", "_g1_committed", &offsetG1Committed, NULL}, {"MemRegion", "_start", &offsetMemRegionStart, NULL}, /* End flag. */ {NULL, NULL, NULL, NULL} }; vmScanner->GetDataFromVMStructs(ofsMap); /* If failure getting offset. */ if (unlikely(offsetG1Committed == -1 || offsetMemRegionStart == -1 || collectedHeap == NULL)) { PRINT_WARN_MSG("Failure getting information form JVM." " info:G1 from:vmStructs"); return false; } /* Calculate about G1GC memory information. */ void *g1Committed = *(void**)incAddress(collectedHeap, offsetG1Committed); void *g1StartAddr = incAddress(g1Committed, offsetMemRegionStart); if (unlikely(g1Committed == NULL || g1StartAddr == NULL)) { PRINT_WARN_MSG("Failure getting information form JVM." " info:G1 from:calculate"); return false; } try { /* Sanity check. */ if (unlikely(maxMemSize <= 0)) { throw 1; } /* Create bitmap to check object collected flag. */ checkObjectMap = new TBitMapMarker(g1StartAddr, maxMemSize); } catch(...) { PRINT_WARN_MSG("Failure allocate object marker bitmap."); return false; } THookFunctionInfo *funcs; SELECT_HOOK_FUNCS(funcs, g1) /* If failure getting function information. */ if (unlikely(!setupOverrideFunction(funcs) || !setupOverrideFunction(g1Event_hook))) { PRINT_WARN_MSG("Failure function overriding. func:g1"); return false; } return true; } /*! * \brief Setting GC hooking enable. * \param enable [in] Is GC hook enable. * \return Process result. */ bool setGCHookState(bool enable) { /* Sanity check. */ if (unlikely(isEnableGCHooking == enable)) { /* Already set state. */ return true; } /* Change state. */ isEnableGCHooking = enable; /* Setting hooking target. */ THookFunctionInfo *list = NULL; if (*useParOld) { SELECT_HOOK_FUNCS(list, parOld) } else if (*useCMS) { /* Switch CMS hooking at new generation. */ THookFunctionInfo *funcs; SELECT_HOOK_FUNCS(funcs, cms_new) switchOverrideFunction(funcs, enable); list = cms_sweep_hook; } else if (*useG1) { /* If users select G1, we prepare TSnapShotContainer NOW! */ snapshotByGC = TSnapShotContainer::getInstance(); /* Switch G1GC event hooking. */ switchOverrideFunction(g1Event_hook, enable); SELECT_HOOK_FUNCS(list, g1) checkObjectMap->clear(); } /* Switch common hooking. */ THookFunctionInfo *parFuncs; SELECT_HOOK_FUNCS(parFuncs, par) if (unlikely(!switchOverrideFunction(parFuncs, enable))) { PRINT_WARN_MSG("Failure switch function overriding. func:par"); return false; } /* Switch adjust pointer hooking. */ if(!jvmInfo->isAfterCR6964458()){ if(unlikely(!switchOverrideFunction(adj_hook, enable))){ PRINT_WARN_MSG("Failure switch function overriding. func:adj-ptr"); return false; } } if (list != NULL) { /* Switch hooking for each GC type. */ if (unlikely(!switchOverrideFunction(list, enable))) { PRINT_WARN_MSG("Failure switch function overriding. func:usingGC"); return false; } } return true; } /*! * \brief Setting JVMTI hooking enable. * \param enable [in] Is JVMTI hook enable. * \return Process result. */ bool setJvmtiHookState(bool enable) { /* Sanity check. */ if (unlikely(isEnableJvmtiHooking == enable)) { /* Already set state. */ return true; } /* Change state. */ isEnableJvmtiHooking = enable; /* Switch JVMTI hooking. */ if (unlikely(!switchOverrideFunction(jvmti_hook, enable))) { PRINT_WARN_MSG("Failure switch function overriding. func:JVMTI"); return false; } return true; } /*! * \brief Initialization of this util. * \param jvmti [in] JVMTI environment object. * \return Process result. */ bool oopUtilInitialize(jvmtiEnv *jvmti) { /* Search symbol in libjvm. */ char *libPath = NULL; jvmti->GetSystemProperty("sun.boot.library.path", &libPath); try{ /* Create symbol finder instance. */ symFinder = new TSymbolFinder(); if(unlikely(!symFinder->loadLibrary(libPath))){ throw 0; } /* Cretae VMStruct scanner instance. */ vmScanner = new TVMStructScanner(symFinder); } catch(...){ PRINT_WARN_MSG("Failure getting symbol information."); jvmti->Deallocate((unsigned char *)libPath); return false; } jvmti->Deallocate((unsigned char *)libPath); /* Setup HotSpot version */ char *versionStr = NULL; if(unlikely(isError(jvmti, jvmti->GetSystemProperty("java.vm.version", &versionStr)))){ PRINT_WARN_MSG("Failure getting JVM version."); return false; } else{ unsigned char major = 0; unsigned char minor = 0; unsigned short build = 0; int result = 0; /* Parse version string. */ result = sscanf(versionStr, "%hhu.%hhu-b%hu", &major, &minor, &build); jvmti->Deallocate((unsigned char *)versionStr); /* If failure parse version string. */ if(unlikely(result != 3)){ PRINT_WARN_MSG("Failure getting symbol information."); return false; } jvmInfo->setHSVersion(MAKE_HS_VERSION(major, minor, build)); } /* Search flag symbol in libjvm. */ searchCommonFlags(); /* Search common function symbol in libjvm. */ if(unlikely(!searchCommonFunction())){ return false; } /* Create pthred key for klassOop. */ if(unlikely(pthread_key_create(&oldKlassOopKey, pThreadKeyDestructor) != 0)){ PRINT_WARN_MSG("Failure create pthread key."); return false; } if(*useG1){ if(unlikely(!jvmInfo->isAfterCR7046558())){ /* Heapstats agent is unsupported G1GC on JDK6. */ PRINT_WARN_MSG("Sorry, G1GC isn't supported in this HotSpot version."); PRINT_WARN_MSG("You should use <= 22.0-b03"); return false; } } return true; } /*! * \brief Finailization of this util. */ void oopUtilFinalize(void) { /* Cleanup. */ if (*useG1) { delete checkObjectMap; checkObjectMap = NULL; } delete vmScanner; vmScanner = NULL; delete symFinder; symFinder = NULL; } /*! * \brief Setup hooking. * \warning Please this function call at after Agent_OnLoad. * \param funcOnGC [in] Pointer of GC 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 funcOnJVMTI, TKlassAdjustCallback funcOnAdjust, TCommonCallback funcOnG1GC, size_t maxMemSize) { /* Set function. */ gcCallbackFunc = funcOnGC; jvmtiIteCallbackFunc = funcOnJVMTI; adjustCallbackFunc = funcOnAdjust; g1FinishCallbackFunc = funcOnG1GC; /* Get common function, variable and offset. */ if (unlikely(!searchCommonInformation())) { return false; } /* Get object. */ collectedHeap = (*(void**)collectedHeap); narrowOffsetBase = (ptrdiff_t)*(void**)narrowOffsetBase; narrowKlassOffsetBase = (ptrdiff_t)*(void**)narrowKlassOffsetBase; /* Setup for WatcherThread. */ if(unlikely(!setupOverrideFunction(watcherThread_hook))){ PRINT_WARN_MSG("Failure function overriding. func:WatcherThread"); return false; } switchOverrideFunction(watcherThread_hook, true); /* Setup for JVMTI. */ if (unlikely(!setupOverrideFunction(jvmti_hook))) { PRINT_WARN_MSG("Failure function overriding. func:JVMTI"); return false; } /* Setup for pointer adjustment. */ if(!jvmInfo->isAfterCR6964458()){ if(unlikely(!setupOverrideFunction(adj_hook))){ PRINT_WARN_MSG("Failure function overriding. func:adj-ptr"); return false; } } /* Setup by using GC type. */ /* Setup parallel GC and GC by user. */ if (unlikely(!setupForParallel())) { return false; } /* Setup for inner GC function. */ if(unlikely(!setupOverrideFunction(innerStart_hook))){ PRINT_WARN_MSG("Failure function overriding. func:common"); return false; } /* Setup each GC type. */ bool result = (*useParallel); if (*useParOld) { result = setupForParallelOld(); } else if (*useCMS) { result = setupForCMS(); } else if (*useG1) { result = setupForG1GC(maxMemSize); } return result; } /*! * \brief Check CMS garbage collector state. * \param state [in] State of CMS garbage collector. * \param gcCause [in] String of GC cause. * \param needSnapShot [out] Is need snapshot now. * \warning Please don't forget call on JVM death. */ void checkCMSState(TGCState state, char *gcCause, bool *needSnapShot) { /* Sanity check. */ if (unlikely(needSnapShot == NULL)) { PRINT_WARN_MSG("Illegal paramter!"); return; } *needSnapShot = false; switch (state) { case gcStart: /* Call on JVMTI GC start. */ if (*CMS_collectorState <= CMS_IDLING) { /* Set stored flag of passed sweep phase. */ *needSnapShot = needSnapShotByCMSPhase; needSnapShotByCMSPhase = false; } else if (*CMS_collectorState == CMS_FINALMARKING) { /* switch hooking for CMS new generation. */ THookFunctionInfo *funcs; SELECT_HOOK_FUNCS(funcs, cms_new) switchOverrideFunction(funcs, true); } break; case gcFinish: /* Call on JVMTI GC finished. */ switch (*CMS_collectorState) { case CMS_MARKING: /* CMS marking phase. */ break; case CMS_SWEEPING: /* CMS sweep phase. */ THookFunctionInfo *funcs; SELECT_HOOK_FUNCS(funcs, cms_new) switchOverrideFunction(funcs, false); needSnapShotByCMSPhase = true; break; default: /* CMS other phase. */ const char *notCMSGCCause[] = { /* Call by Java.Lang.System. */ "System.gc()", /* Call by JVMTI. */ "JvmtiEnv ForceGarbageCollection", /* End flag. */ NULL }; if (likely(gcCause != NULL)) { /* Check this GC. */ for (int i = 0; notCMSGCCause[i] != NULL; i++) { if (strcmp(gcCause, notCMSGCCause[i]) == 0) { /* GC invoke by user or service without CMS. */ *needSnapShot = true; break; } } } } break; case gcLast: /* Call on JVM is terminating. */ /* Set stored flag of passed sweep phase. */ *needSnapShot = needSnapShotByCMSPhase; needSnapShotByCMSPhase = false; break; default: /* Not reached here. */ PRINT_WARN_MSG("Illegal GC state."); } } /*! * \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){ isInvokeGCManyTimes = false; gcInterruptCallbackFunc = interruptEvent; return switchOverrideFunction(innerStart_hook, enableHook); } /*! * \brief "is_in_permanent" for after CR6964458. * This function always return false because this CR means PermGen Removal. * \param thisptr [in] G1CollectedHeap/GenCollectedHeap/ParallelScavengeHeap * class instance. * \param oop [in] (C++) Java object. * \return always false. */ bool is_in_permanent_AfterCR6964458(void *thisptr, void *oop){ return false; }