Mercurial > hg > release > heapstats-1.1
view agent/src/oopUtil.cpp @ 37:80933f82c4c0
Bug 2365: Adapt to G1GC hook points of JDK-8049421
reviewed-by: yasuenag
author | KUBOTA Yuji <kubota.yuji@lab.ntt.co.jp> |
---|---|
date | Mon, 18 May 2015 00:36:35 +0900 |
parents | 54cf38a69dca |
children | 0f15d6873c2d |
line wrap: on
line source
/*! * \file oopUtil.cpp * \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. * */ #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" /* Function define. */ /* Override functions. */ /* Macros for override function */ /*! * \brief Override function define macro for a function. */ #define DEFINE_OVERRIDE_FUNC_N(prefix, num) \ extern "C" void *prefix##_override_func_##num; /*! * \brief Override function define macro for one function. */ #define DEFINE_OVERRIDE_FUNC_1(prefix) \ DEFINE_OVERRIDE_FUNC_N(prefix, 0) /*! * \brief Override function define macro for two function. */ #define DEFINE_OVERRIDE_FUNC_2(prefix) \ DEFINE_OVERRIDE_FUNC_N(prefix, 0) \ DEFINE_OVERRIDE_FUNC_N(prefix, 1) /*! * \brief Override function define macro for three function. */ #define DEFINE_OVERRIDE_FUNC_3(prefix) \ DEFINE_OVERRIDE_FUNC_N(prefix, 0) \ DEFINE_OVERRIDE_FUNC_N(prefix, 1) \ DEFINE_OVERRIDE_FUNC_N(prefix, 2) /*! * \brief Override function define macro for four function. */ #define DEFINE_OVERRIDE_FUNC_4(prefix) \ DEFINE_OVERRIDE_FUNC_N(prefix, 0) \ DEFINE_OVERRIDE_FUNC_N(prefix, 1) \ DEFINE_OVERRIDE_FUNC_N(prefix, 2) \ DEFINE_OVERRIDE_FUNC_N(prefix, 3) /*! * \brief Override function define macro for eight function. */ #define DEFINE_OVERRIDE_FUNC_8(prefix) \ DEFINE_OVERRIDE_FUNC_N(prefix, 0) \ DEFINE_OVERRIDE_FUNC_N(prefix, 1) \ DEFINE_OVERRIDE_FUNC_N(prefix, 2) \ DEFINE_OVERRIDE_FUNC_N(prefix, 3) \ DEFINE_OVERRIDE_FUNC_N(prefix, 4) \ DEFINE_OVERRIDE_FUNC_N(prefix, 5) \ DEFINE_OVERRIDE_FUNC_N(prefix, 6) \ DEFINE_OVERRIDE_FUNC_N(prefix, 7) /*! * \brief Override function define macro for nine function. */ #define DEFINE_OVERRIDE_FUNC_9(prefix) \ DEFINE_OVERRIDE_FUNC_N(prefix, 0) \ DEFINE_OVERRIDE_FUNC_N(prefix, 1) \ DEFINE_OVERRIDE_FUNC_N(prefix, 2) \ DEFINE_OVERRIDE_FUNC_N(prefix, 3) \ DEFINE_OVERRIDE_FUNC_N(prefix, 4) \ DEFINE_OVERRIDE_FUNC_N(prefix, 5) \ DEFINE_OVERRIDE_FUNC_N(prefix, 6) \ DEFINE_OVERRIDE_FUNC_N(prefix, 7) \ DEFINE_OVERRIDE_FUNC_N(prefix, 8) /*! * \brief Select override function information macro. */ #define SELECT_HOOK_FUNCS(prefix) \ if (enableCR8049421) { \ prefix##_hook = CR8049421_##prefix##_hook; \ } else if (enableCR8027746) { \ prefix##_hook = CR8027746_##prefix##_hook; \ } else if (enableCR8000213) { \ prefix##_hook = CR8000213_##prefix##_hook; \ } else if (enableCR6964458) { \ prefix##_hook = CR6964458_##prefix##_hook; \ } else { \ prefix##_hook = default_##prefix##_hook; \ } /* These functions is defined in override.S. */ /*! * \brief Override function for heap object on parallelGC. */ DEFINE_OVERRIDE_FUNC_4(par); /*! * \brief Override function for heap object on parallelOldGC. */ DEFINE_OVERRIDE_FUNC_4(parOld); /*! * \brief Override function for sweep at old gen on CMSGC. */ DEFINE_OVERRIDE_FUNC_1(cms_sweep); /*! * \brief Override function for heap object at new gen on CMSGC. */ DEFINE_OVERRIDE_FUNC_4(cms_new); /*! * \brief Override function for heap object on G1GC. */ DEFINE_OVERRIDE_FUNC_9(g1); /*! * \brief Override function for cleanup and System.gc() event on G1GC. */ DEFINE_OVERRIDE_FUNC_3(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) /* Variable. */ /* Define JVM paramter pointer variable for calling from external. */ /*! * \brief Value of "-XX:UseCompressedOops" or "-XX:UseCompressedClassPointers". */ bool isCOOP = false; /*! * \brief Value of "-XX:UseParallelGC". */ bool useParallel = false; /*! * \brief Value of "-XX:UseParallelOldGC". */ bool useParOld = false; /*! * \brief Value of "-XX:UseConcMarkSweepGC". */ bool useCMS = false; /*! * \brief Value of "-XX:UseG1GC". */ bool useG1 = false; /*! * \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; /*! * \brief Function pointer for "instanceKlass::class_loader()". */ TGetClassLoader getClassLoaderForInstanceKlass = NULL; /*! * \brief Function pointer for "objArrayKlass::class_loader()". */ TGetClassLoader getClassLoaderForObjArrayKlass = 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 "Klass" class in JVM. */ uint64_t clsSizeKlass = 0; /*! * \brief Size of "instanceKlass" class in JVM. */ uint64_t clsSizeInstanceKlass = 0; /*! * \brief Size of "arrayOopDesc" class in JVM. */ uint64_t clsSizeArrayOopDesc = 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; /*! * \brief Offset of "instanceKlass" class's "_vtable_len" field. * This field is stored vtable size. */ off_t ofsVTableSizeAtInsKlass = -1; /*! * \brief Offset of "instanceKlass" class's "_itable_len" field. * This field is stored itable size. */ off_t ofsITableSizeAtInsKlass = -1; /*! * \brief Offset of "instanceKlass" class's "_static_field_size" field. * This field is stored static field size. */ off_t ofsStaticFieldSizeAtInsKlass = -1; /*! * \brief Offset of "instanceKlass" class's "_nonstatic_oop_map_size" field. * This field is stored static field size. */ off_t ofsNonstatiOopMapSizeAtInsKlass = -1; /*! * \brief Offset of "oopDesc" class's "klass_offset_in_bytes" field. * This field is stored static field size. */ off_t ofsKlassOffsetInBytesAtOopDesc = -1; /* Variable for environment information. */ /*! * \brief Pointer of COOP base address. */ ptrdiff_t narrowOffsetBase = 0; /*! * \brief Value of COOP shift bits. */ int narrowOffsetShift = 0; /*! * \brief Pointer of Klass COOP base address. */ ptrdiff_t narrowKlassOffsetBase = 0; /*! * \brief Value of Klass COOP shift bits. */ int narrowKlassOffsetShift = 0; /*! * \brief Lock bit mask.<br> * Value of "markOopDesc" class's "lock_mask_in_place" constant value. */ uint64_t lockMaskInPlaceMarkOop = 0; /* Variable for CMS marking bitmap. */ /*! * \brief Pointer of CMS marking bitmap start word. */ void *cmsBitMap_startWord = NULL; /*! * \brief Value of CMS bitmap shifter. */ int cmsBitMap_shifter = 0; /*! * \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 ; /*! * \brief Mask bit data of BitsPerWord.<br> * Used by CMSGC("isMarkedObject") process. */ int BitsPerWordMask = 0; /*! * \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 for default. */ THookFunctionInfo default_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", &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 CR8000213. */ THookFunctionInfo CR8000213_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 Pointers of hook information on parallelGC for several CRs.<br> * These CRs have no impact on parallelGC, so refer to the last. */ #define CR8027746_par_hook CR8000213_par_hook #define CR8049421_par_hook CR8000213_par_hook /*! * \brief Pointer of hook information on parallelGC. */ THookFunctionInfo *par_hook = NULL; /*! * \brief Pointer of hook information on parallelOldGC for default. */ THookFunctionInfo default_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", &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 CR8000213. */ THookFunctionInfo CR8000213_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 Pointers of hook information on parallelOldGC for several CRs.<br> * These CRs have no impact on parallelOldGC, so refer to the last. */ #define CR8027746_parOld_hook CR8000213_parOld_hook #define CR8049421_parOld_hook CR8000213_parOld_hook /*! * \brief Pointer of hook information on parallelGC. */ THookFunctionInfo *parOld_hook = NULL; /*! * \brief Pointer of hook information on CMSGC for default. */ THookFunctionInfo default_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_sweep_hook = default_cms_sweep_hook; /*! * \brief Pointer of hook information on CMSGC for default. */ THookFunctionInfo default_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", &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" "EP7oopDescP18ExtendedOopClosure", &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 CR8000213. */ THookFunctionInfo CR8000213_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" "EP7oopDescP18ExtendedOopClosure", &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 Pointers of hook information on CMSGC for several CRs.<br> * These CRs have no impact on CMSGC, so refer to the last. */ #define CR8027746_cms_new_hook CR8000213_cms_new_hook #define CR8049421_cms_new_hook CR8000213_cms_new_hook /*! * \brief Pointer of hook information on parallelGC. */ THookFunctionInfo *cms_new_hook = NULL; /*! * \brief Pointer of hook information on G1GC for default. */ THookFunctionInfo default_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", &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_iterateEP7oopDescP18ExtendedOopClosure", &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 CR8000213. */ THookFunctionInfo CR8000213_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_iterateEP7oopDescP18ExtendedOopClosure", &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 CR8027746. */ THookFunctionInfo CR8027746_g1_hook[] = { HOOK_FUNC("_ZTV16G1ParCopyClosureIL9G1Barrier0ELb1EE", "_ZN16G1ParCopyClosureIL9G1Barrier0ELb1EE6do_oopEPP7oopDesc", &g1_override_func_0, NULL), HOOK_FUNC("_ZTV16G1ParCopyClosureIL9G1Barrier0ELb1EE", "_ZN16G1ParCopyClosureIL9G1Barrier0ELb1EE6do_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_iterateEP7oopDescP18ExtendedOopClosure", &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 JDK-8049421. */ THookFunctionInfo CR8049421_g1_hook[] = { HOOK_FUNC("_ZTV16G1ParCopyClosureIL9G1Barrier0EL6G1Mark1EE", "_ZN16G1ParCopyClosureIL9G1Barrier0EL6G1Mark1EE6do_oopEPP7oopDesc", &g1_override_func_0, NULL), HOOK_FUNC("_ZTV16G1ParCopyClosureIL9G1Barrier0EL6G1Mark1EE", "_ZN16G1ParCopyClosureIL9G1Barrier0EL6G1Mark1EE6do_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_iterateEP7oopDescP18ExtendedOopClosure", &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 parallelGC. */ THookFunctionInfo *g1_hook = NULL; /*! * \brief Pointer of hook information on G1GC cleanup event for default. */ THookFunctionInfo default_g1Event_hook[] = { HOOK_FUNC("_ZTV9CMCleanUp", "_ZN9CMCleanUp7do_voidEv", &g1Event_override_func_0, NULL), HOOK_FUNC("_ZTV15G1CollectedHeap", "_ZN15G1CollectedHeap11gc_prologueEb", &g1Event_override_func_1, NULL), HOOK_FUNC("_ZTV15G1CollectedHeap", "_ZN15G1CollectedHeap11gc_epilogueEb", &g1Event_override_func_2, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook information on G1GC cleanup event. */ THookFunctionInfo *g1Event_hook = default_g1Event_hook; /*! * \brief Pointer of hook change and adjust oop with GC for default. */ THookFunctionInfo default_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 change and adjust oop with GC. */ THookFunctionInfo *adj_hook = default_adj_hook; /*! * \brief Pointer of hook oop iterate with JVMTI HeapOverIterate for default. */ THookFunctionInfo default_jvmti_hook[] = { HOOK_FUNC("_ZTV28IterateOverHeapObjectClosure", "_ZN28IterateOverHeapObjectClosure9do_objectEP7oopDesc", &jvmti_override_func_0, NULL), HOOK_FUNC_END }; /*! * \brief Pointer of hook oop iterate with JVMTI HeapOverIterate. */ THookFunctionInfo *jvmti_hook = default_jvmti_hook; /*! * \brief Pointer of hook inner GC function for default. */ THookFunctionInfo default_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 hook inner GC function. */ THookFunctionInfo *innerStart_hook = default_innerStart_hook; /*! * \brief Pointer of WatcherThread hook. */ THookFunctionInfo default_watcherThread_hook[] = { HOOK_FUNC("_ZTV13WatcherThread", "_ZN13WatcherThread3runEv", &watcherThread_override_func_0, (void *)callbackForWatcherThreadRun), HOOK_FUNC_END }; /*! * \brief Pointer of hook WatcherThread. */ THookFunctionInfo *watcherThread_hook = default_watcherThread_hook; /* Event callback for outter. */ /*! * \brief Callback function for general GC function hooking. */ THeapObjectCallback gcCallbackFunc = NULL; /*! * \brief Callback function for CMSGC function hooking. */ THeapObjectCallback cmsCallbackFunc = 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; /* Variable for hotspot version. */ /*! * \brief JVM version. */ unsigned int hotSpotVersion = 0U; /*! * \brief Flag of JVM is applyed CR#7017732.<br> * Decision for 7017732: * move static fields into Class to prepare for perm gen removal. * \sa http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7017732 * \sa http://hg.openjdk.java.net/hsx/hotspot-rt-gate/hotspot/rev/c7f3d0b4570f */ bool enableCR7017732 = false; /*! * \brief Flag of JVM is applyed CR#6964458.<br> * Decision for 6964458: * Reimplement class meta-data storage to use native memory. * (PermGen Removal) * \sa http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6964458 * \sa http://hg.openjdk.java.net/hsx/hotspot-rt-gate/hotspot/rev/da91efe96a93 */ bool enableCR6964458 = false; /*! * \brief Flag of JVM is applyed CR#8000213.<br> * Decision for CR8000213: * NPG: Should have renamed arrayKlass and typeArrayKlass. * \sa http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8000213 * \sa http://hg.openjdk.java.net/hsx/hotspot-rt/hotspot/rev/d8ce2825b193 */ bool enableCR8000213 = false; /*! * \brief Flag of JVM is applyed JDK-8027746.<br> * Remove do_gen_barrier template parameter in G1ParCopyClosure * \sa https://bugs.openjdk.java.net/browse/JDK-8027746 * \sa http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/c685ef164975 */ bool enableCR8027746 = false; /*! * \brief Flag of JVM is applyed CR#8004883.<br> * Decision for CR8004883: * 8004883: NPG: clean up anonymous class fix * \sa http://bugs.sun.com/view_bug.do?bug_id=8004883 * \sa http://hg.openjdk.java.net/hsx/hotspot-gc/hotspot/rev/30866cd626b0 */ bool enableCR8004883 = false; /*! * \brief Flag of JVM is applyed CR#8003424.<br> * Decision for CR8003424: * 8003424: Enable Class Data Sharing for CompressedOops * \sa http://bugs.sun.com/view_bug.do?bug_id=8003424 * \sa http://hg.openjdk.java.net/hsx/hotspot-rt/hotspot/rev/740e263c80c6 */ bool enableCR8003424 = false; /*! * \brief Flag of JVM is applyed CR#8015107.<br> * Decision for CR8015107: * 8015107: NPG: Use consistent naming for metaspace concepts * \sa https://bugs.openjdk.java.net/browse/JDK-8015107 */ bool enableCR8015107 = false; /*! * \brief Flag of JVM is applyed JDK-8049421.<br> * G1 Class Unloading after completing a concurrent mark cycle * \sa https://bugs.openjdk.java.net/browse/JDK-8049421 * \sa http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/rev/2c6ef90f030a */ bool enableCR8049421 = false; /* Variable for hotspot version. */ /*! * \brief Flag of called parallel gc on using CMS gc. */ bool isInvokedParallelGC = false; /*! * \brief VTable list which should be hooked. */ void *VTableForTypeArrayOopClosure[2] __attribute__((aligned(16))); /* Macro. */ /* Symbol macro. */ /*! * \brief String of symbol which is "is_in_permanent" function on parallel GC. */ #define IS_IN_PERM_ON_PARALLEL_GC_SYMBOL \ "_ZNK20ParallelScavengeHeap15is_in_permanentEPKv" /*! * \brief String of symbol which is "is_in_permanent" function on other GC. */ #define IS_IN_PERM_ON_OTHER_GC_SYMBOL \ "_ZNK10SharedHeap15is_in_permanentEPKv" /*! * \brief Symbol of "JvmtiEnv::GetObjectSize" macro. */ #ifdef __x86_64__ #define SYMBOL_GETOBJCTSIZE "_ZN8JvmtiEnv13GetObjectSizeEP8_jobjectPl" #else #define SYMBOL_GETOBJCTSIZE "_ZN8JvmtiEnv13GetObjectSizeEP8_jobjectPx" #endif /*! * \brief String of symbol which is "java.lang.Class.as_klassOop" function. */ #define AS_KLASSOOP_SYMBOL "_ZN15java_lang_Class11as_klassOopEP7oopDesc" /*! * \brief String of symbol which is "java.lang.Class.as_klass" function.<br /> * This function is for after CR6964458. */ #define AS_KLASS_SYMBOL "_ZN15java_lang_Class8as_KlassEP7oopDesc" /*! * \brief String of symbol which is safepoint state variable. */ #define SAFEPOINT_STATE_SYMBOL "_ZN20SafepointSynchronize6_stateE" /*! * \brief String of symbol which is function get class loader for instance. */ #define GET_CLSLOADER_FOR_INSTANCE_SYMBOL "_ZNK13instanceKlass12class_loaderEv" /*! * \brief String of symbol which is function get class loader for instance * after CR#8004883. */ #define CR8004883_GET_CLSLOADER_FOR_INSTANCE_SYMBOL "_ZNK13InstanceKlass12klass_holderEv" /*! * \brief String of symbol which is function get class loader for object array. */ #define GET_CLSLOADER_FOR_OBJARY_SYMBOL "_ZNK13objArrayKlass12class_loaderEv" /*! * \brief String of symbol which is function get class loader for object array * after CR#8004883. */ #define CR8004883_GET_CLSLOADER_FOR_OBJARY_SYMBOL "_ZNK5Klass12klass_holderEv" /* Other macro. */ /*! * \brief Calculate pointer align macro. */ #define ALIGN_POINTER_OFFSET(size) \ (ALIGN_SIZE_UP((size), HeapWordsPerLong)) /*! * \brief Header macro for array array class. Chars of "[[". */ #define HEADER_KLASS_ARRAY_ARRAY 0x5b5b #ifdef WORDS_BIGENDIAN /*! * \brief Header macro for object array class. Chars of "[L". */ #define HEADER_KLASS_OBJ_ARRAY 0x5b4c #else /*! * \brief Header macro for object array class. Chars of "[L". */ #define HEADER_KLASS_OBJ_ARRAY 0x4c5b #endif /*! * \brief Header macro for array class. Chars of "[". */ #define HEADER_KLASS_ARRAY 0x5b /* 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 (unlikely(klassOop == NULL || enableCR6964458)) { return klassOop; } 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){ /* Sanity check. */ if (unlikely(oop == NULL)) { return NULL; } void *tempAddr = 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); } /*! * \brief Get first field object block for "InstanceKlass". * \param klassOop [in] Class information object(Inner "Klass" class). * \return Oop's field information inner class object("OopMapBlock" class). * \sa hotspot/src/share/vm/oops/instanceKlass.hpp * InstanceKlass::start_of_static_fields() */ inline void *getBeginBlock(void *klassOop) { /* * Memory map of "klass(InstanceKlass)" class. * - Klass object head pointer - * - OopDesc - * - InstanceKlass - * - Java's v-table - * - Java's i-table - * - Static field oops(Notice) - * - Non-Static field oops - * Notice - By CR7017732, this area is removed. */ void *klass = getKlassFromKlassOop(klassOop); if (unlikely(klass == NULL)) { return NULL; } /* Move to v-table head. */ off_t ofsStartVTable = enableCR6964458 ? ALIGN_POINTER_OFFSET(clsSizeInstanceKlass / HeapWordSize) : ALIGN_POINTER_OFFSET((clsSizeOopDesc / HeapWordSize) + (clsSizeInstanceKlass / HeapWordSize)); void *startVTablePtr = (intptr_t*)klassOop + ofsStartVTable; int vTableLen = *(int*)incAddress(klass, ofsVTableSizeAtInsKlass); /* Increment v-table size. */ void *startITablePtr = (intptr_t*)startVTablePtr + ALIGN_POINTER_OFFSET(vTableLen); int iTableLen = *(int*)incAddress(klass, ofsITableSizeAtInsKlass); /* Increment i-table size. */ void *startStaticFieldPtr = (intptr_t*)startITablePtr + ALIGN_POINTER_OFFSET(iTableLen); if (enableCR7017732) { return startStaticFieldPtr; } /* Increment static field size. */ int staticFieldSize = *(int*)incAddress(klass, ofsStaticFieldSizeAtInsKlass); return (intptr_t*)startStaticFieldPtr + staticFieldSize; } /*! * \brief Get number of field object blocks for "InstanceKlass". * \param instanceKlass [in] Class information object about "InstanceKlass". * (Inner "Klass" class) * \return Oop's field information inner class object("OopMapBlock" class). * \sa hotspot/src/share/vm/oops/instanceKlass.hpp * InstanceKlass::nonstatic_oop_map_count() */ inline int getBlockCount(void *instanceKlass) { /* Get total field size. */ int nonstaticFieldSize = *(int*)incAddress(instanceKlass, ofsNonstatiOopMapSizeAtInsKlass); /* Get single field size. */ int sizeInWord = ALIGN_SIZE_UP(sizeof(TOopMapBlock), HeapWordSize) >> LogHeapWordSize; /* Calculate number of fields. */ return nonstaticFieldSize / sizeInWord; } /*! * \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) { TOopType result = otIllegal; if (likely(klassName != NULL)) { if (*(unsigned short*)klassName == HEADER_KLASS_ARRAY_ARRAY) { result = otArrayArray; } else if (*(unsigned short*)klassName == HEADER_KLASS_OBJ_ARRAY) { result = otObjArarry; } else if (*klassName == HEADER_KLASS_ARRAY) { result = otArray; } else { /* Expected class name is instance class. */ result = otInstance; } } return result; } /*! * \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) { void *classLoader = NULL; void *klass = getKlassFromKlassOop(klassOop); /* Sanity check. */ if (unlikely(klassOop == NULL || klass == NULL)) { return NULL; } switch (type) { case otObjArarry: classLoader = getClassLoaderForObjArrayKlass(klass); break; case otInstance: classLoader = getClassLoaderForInstanceKlass(klass); break; case otArray: case otArrayArray: /* * This type oop has no class loader. * Because such oop is loaded by system bootstrap class loader. * Or the class is loaded at system initialize (e.g. "Universe"). */ default: ; } return classLoader; } /*! * \brief This dummy function for "is_in_permanent".<br> * \param thisptr [in] Heap object instance. * \param oop [in] Java object. * \return Always value is "false". */ bool dummyIsInPermanent(void *thisptr, void *oop) { return false; } /* Function for callback. */ /*! * \brief Follow oop field block. * \param event [in] Callback function. * \param fieldOops [in] Pointer of field block head. * \param count [in] Count of field block. * \param data [in] User expected data. */ inline void followFieldBlock(THeapObjectCallback event, void **fieldOops, const unsigned int count, void* data) { /* Follow oop at each block. */ for (unsigned int idx = 0; idx < count; idx++) { void *childOop = NULL; /* Sanity check. */ if (unlikely(fieldOops == NULL)) { continue; } /* Get child oop and move next array item. */ if (isCOOP) { /* If this field is not null. */ if (likely((*(unsigned int*)fieldOops) != 0)) { childOop = getWideOop(*(unsigned int*)fieldOops); } fieldOops = (void**)((unsigned int*)fieldOops + 1); } else { childOop = *fieldOops++; } /* Check oops isn't in permanent generation. */ if (childOop != NULL && !is_in_permanent(collectedHeap, childOop)) { /* Invoke callback. */ event(childOop, data); } } } /*! * \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) { /* Sanity check. */ if (unlikely(klassOop == NULL || offsets == NULL || count == NULL)) { return; } void *klass = getKlassFromKlassOop(klassOop); if (unlikely(klass == NULL)) { return; } TOopMapBlock *block = NULL; /* Get field blocks. */ switch (oopType) { case otInstance: { int blockCount = getBlockCount(klass); TOopMapBlock *mapBlock = (TOopMapBlock*)getBeginBlock(klassOop); /* Allocate block offset records. */ block = (TOopMapBlock*)malloc(sizeof(TOopMapBlock) * blockCount); if (likely(mapBlock != NULL && block != NULL && blockCount > 0)) { /* Follow each block. */ for (int i = 0; i < blockCount; i++) { /* Store block information. */ block[i].offset = mapBlock->offset; block[i].count = mapBlock->count; /* Go next block. */ mapBlock++; } (*offsets) = block; (*count) = blockCount; } else { /* If class has no field. */ if (blockCount == 0) { (*offsets) = NULL; (*count) = 0; } /* Deallocate memory. */ free(block); } break; } case otObjArarry: { /* Allocate a block offset record. */ block = (TOopMapBlock*)malloc(sizeof(TOopMapBlock)); if (likely(block != NULL)) { /* * Get array's length field and array field offset. * But such fields isn't define by C++. So be cafeful. * Please see below source file about detail implementation. * hostpost/src/share/vm/oops/arrayOop.hpp */ block->count = isCOOP ? (ofsKlassAtOop + clsSizeNarrowOop) : clsSizeArrayOopDesc; block->offset = ALIGN_SIZE_UP(block->count + sizeof(int), HeapWordSize); (*offsets) = block; (*count) = 1; } break; } default: /* The oop has no field. */ ; } } /*! * \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) { /* Sanity check. */ if (unlikely(oop == NULL || event == NULL || ofsData == NULL || ofsDataSize == NULL || (*ofsData) == NULL || (*ofsDataSize) <= 0)) { return; } /* If oop has no field. */ if (unlikely(!hasOopField(oopType))) { return; } /* Use expected data by function calling arguments. */ TOopMapBlock *offsets = (*ofsData); int offsetCount = (*ofsDataSize); if (oopType == otInstance) { /* Iterate each oop field block as "Instance klass". */ for (TOopMapBlock *endOfs = offsets + offsetCount; offsets < endOfs; offsets++) { followFieldBlock(event, (void**)incAddress(oop, offsets->offset), offsets->count, data); } } else { /* Iterate each oop field block as "ObjArray klass". */ followFieldBlock(event, (void**)incAddress(oop, offsets->offset), *(int*)incAddress(oop, offsets->count), data); } } /*! * \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 callback by GC. */ gcCallbackFunc(oop, NULL); isInvokedParallelGC = true; } /*! * \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 callback by GC. */ gcCallbackFunc(oop, NULL); isInvokedParallelGC = true; } /*! * \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. */ gcCallbackFunc(*oop, NULL); } /*! * \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; } /* Invoke callback by CMS GC. */ cmsCallbackFunc(oop, NULL); } else if(useG1){ if(checkObjectMap->checkAndMark(oop)){ /* Object is already collected by G1GC collector. */ return; } /* Invoke callback by GC. */ gcCallbackFunc(oop, NULL); isInvokedParallelGC = true; } } /*! * \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 callback by CMS GC. */ cmsCallbackFunc(oop, NULL); } } /*! * \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) { /* Invoke callback by JVMTI. */ jvmtiIteCallbackFunc(oop, NULL); } /*! * \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. * \param isFull [in] Is this event FullGC? */ extern "C" void callbackForG1Full(bool isFull){ /* This function must be processed when FullGC occurs. * e.g. System.gc(), evacuation failure, etc... */ if(!isFull){ return; } /* * Disable G1 callback function: * OopClosure for typeArrayKlass is called by G1 FullCollection. */ switchOverrideFunction(g1_hook, false); /* Discard existed snapshot data */ snapshotByGC->clear(false); checkObjectMap->clear(); } /*! * \brief Callback function for after System.gc() on using G1GC. * \param isFull [in] Is this event FullGC? */ extern "C" void callbackForG1FullReturn(bool isFull){ /* This function must be processed when FullGC occurs. * e.g. System.gc(), evacuation failure, etc... */ if(!isFull){ return; } /* Restore G1 callback. */ switchOverrideFunction(g1_hook, 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) { int *narrowOffsetShiftBuf = NULL; int *narrowKlassOffsetShiftBuf = NULL; /* List of common field offset. */ TOffsetNameMap ofsMap[] = { {"Universe", "_collectedHeap", NULL, &collectedHeap}, {"Universe", "_narrow_oop._base", NULL, (void **)&narrowOffsetBase}, {"Universe", "_narrow_oop._shift", NULL, (void **)&narrowOffsetShiftBuf}, {"Universe", "_narrow_klass._base", NULL, (void **)&narrowKlassOffsetBase}, {"Universe", "_narrow_klass._shift", NULL, (void **)&narrowKlassOffsetShiftBuf}, {"oopDesc", "_metadata._klass", &ofsKlassAtOop, NULL}, {"oopDesc", "_metadata._compressed_klass", &ofsCoopKlassAtOop, NULL}, {"oopDesc", "_mark", &ofsMarkAtOop, NULL}, {"Klass", "_name", &ofsNameAtKlass, NULL}, /* * For CR6990754. * Use native memory and reference counting to implement SymbolTable. */ {"symbolOopDesc", "_length", &ofsLengthAtSymbol, NULL}, {"symbolOopDesc", "_body", &ofsBodyAtSymbol, NULL}, {"Symbol", "_length", &ofsLengthAtSymbol, NULL}, {"Symbol", "_body", &ofsBodyAtSymbol, NULL}, {"instanceKlass", "_vtable_len", &ofsVTableSizeAtInsKlass, NULL}, {"instanceKlass", "_itable_len", &ofsITableSizeAtInsKlass, NULL}, {"instanceKlass", "_static_field_size", &ofsStaticFieldSizeAtInsKlass, NULL}, {"instanceKlass", "_nonstatic_oop_map_size", &ofsNonstatiOopMapSizeAtInsKlass, NULL}, /* For CR6964458 */ {"InstanceKlass", "_vtable_len", &ofsVTableSizeAtInsKlass, NULL}, {"InstanceKlass", "_itable_len", &ofsITableSizeAtInsKlass, NULL}, {"InstanceKlass", "_static_field_size", &ofsStaticFieldSizeAtInsKlass, NULL}, {"InstanceKlass", "_nonstatic_oop_map_size", &ofsNonstatiOopMapSizeAtInsKlass, NULL}, /* End flag. */ {NULL, NULL, NULL, NULL} }; vmScanner->GetDataFromVMStructs(ofsMap); /* If failure getting common field offset information. */ if (unlikely(collectedHeap == NULL || narrowOffsetBase == 0 || narrowOffsetShiftBuf == NULL || ofsKlassAtOop == -1 || ofsCoopKlassAtOop == -1 || ofsNameAtKlass == -1 || ofsLengthAtSymbol == -1 || ofsBodyAtSymbol == -1 || ofsVTableSizeAtInsKlass == -1 || ofsITableSizeAtInsKlass == -1 || (!enableCR7017732 && (ofsStaticFieldSizeAtInsKlass == -1)) || ofsNonstatiOopMapSizeAtInsKlass == -1)) { PRINT_WARN_MSG("Failure getting information form JVM." " info:Common from:VMStructs"); return false; } narrowOffsetShift = *narrowOffsetShiftBuf; if(!enableCR8003424){ narrowKlassOffsetBase = narrowOffsetBase; narrowKlassOffsetShift = narrowOffsetShift; } else{ narrowKlassOffsetShift = *narrowKlassOffsetShiftBuf; } /* List of common class size. */ TTypeSizeMap typeMap[] = { /* * After CR6964458. * Not exists class "klassOopDesc". */ {"klassOopDesc", &clsSizeKlassOop}, {"oopDesc", &clsSizeOopDesc}, {"instanceKlass", &clsSizeInstanceKlass}, {"InstanceKlass", &clsSizeInstanceKlass}, {"arrayOopDesc", &clsSizeArrayOopDesc}, {"narrowOop", &clsSizeNarrowOop}, /* End flag. */ {NULL, NULL} }; vmScanner->GetDataFromVMTypes(typeMap); /* If failure getting common class size information. */ if (unlikely((!enableCR6964458 && clsSizeKlassOop == 0) || clsSizeOopDesc == 0 || clsSizeInstanceKlass == 0 || clsSizeArrayOopDesc == 0 || clsSizeNarrowOop == 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; } /* List of integer constant data target. */ TIntConstMap intMap[] = { {"HeapWordSize", &HeapWordSize}, {"LogHeapWordSize", &LogHeapWordSize}, /* End flag. */ {NULL, NULL} }; vmScanner->GetDataFromVMIntConstants(intMap); return true; } /*! * \brief Search common flag. * \return Process result. */ bool 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 symbol not found. */ if (unlikely(tempPtr == NULL)) { PRINT_WARN_MSG_HEADER << "Java symbol not found." << " symbol:\"" << flagList[i].symbolStr << "\"" << NEWLINE; return false; } *(flagList[i].flagPtr) = *tempPtr; } #ifdef __LP64__ if(enableCR6964458){ bool *tempPtr = NULL; const char *target_sym = enableCR8015107 ? "UseCompressedClassPointers" : "UseCompressedKlassPointers"; /* Search symbol. */ tempPtr = (bool*)symFinder->findSymbol(target_sym); /* If symbol not found. */ 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 } /* Search symbol for integer information. */ 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 integer symbol not found, search sub-symbol. */ if (unlikely(intPos == NULL)) { intPos = (int*)symFinder->findSymbol(intSymList[i].subSymbol); } /* If integer symbol and sub-symbol not found. */ if (unlikely(intPos == NULL)) { PRINT_DEBUG_MSG_HEADER << "Java symbol not found, using default value instead." << " symbol:\"" << intSymList[i].symbol << "\"" << NEWLINE; } else { (*intSymList[i].pointer) = (*intPos); } } return true; } /*! * \brief Search common function. * \return Process result. */ bool searchCommonFunction(void) { /* Search "is_in_permanent" function symbol. */ if (enableCR6964458) { /* Perm gen isn't exists. */ is_in_permanent = (THeap_IsInPermanent)&dummyIsInPermanent; } else if (useParallel || useParOld){ is_in_permanent = (THeap_IsInPermanent)symFinder->findSymbol( IS_IN_PERM_ON_PARALLEL_GC_SYMBOL); } else { is_in_permanent = (THeap_IsInPermanent)symFinder->findSymbol( IS_IN_PERM_ON_OTHER_GC_SYMBOL); } /* If not found "is_in_permanent" function symbol. */ if (unlikely(is_in_permanent == NULL)) { PRINT_WARN_MSG("Java symbol not found. 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("Java symbol not found. symbol:\"GetObjectSize\""); return false; } /* Search "as_klassOop" function symbol. */ asKlassOop = (TJavaLangClass_AsKlassOop)symFinder->findSymbol( (enableCR6964458) ? AS_KLASS_SYMBOL : AS_KLASSOOP_SYMBOL); /* If not found "as_klassOop" function symbol. */ if (unlikely(asKlassOop == NULL)) { PRINT_WARN_MSG("Java symbol not found. symbol:\"as_klassOop\""); return false; } /* Search symbol of variable stored safepoint state. */ safePointState = (int*)symFinder->findSymbol(SAFEPOINT_STATE_SYMBOL); /* If not found "_state" variable symbol. */ if (unlikely(safePointState == NULL)) { PRINT_WARN_MSG("Java symbol not found. symbol:\"safepoint_state\""); return false; } /* Search symbol of function getting classloader. */ if(enableCR8004883){ getClassLoaderForInstanceKlass = (TGetClassLoader)symFinder->findSymbol( CR8004883_GET_CLSLOADER_FOR_INSTANCE_SYMBOL); getClassLoaderForObjArrayKlass = (TGetClassLoader)symFinder->findSymbol( CR8004883_GET_CLSLOADER_FOR_OBJARY_SYMBOL); } else{ getClassLoaderForInstanceKlass = (TGetClassLoader)symFinder->findSymbol( GET_CLSLOADER_FOR_INSTANCE_SYMBOL); getClassLoaderForObjArrayKlass = (TGetClassLoader)symFinder->findSymbol( GET_CLSLOADER_FOR_OBJARY_SYMBOL); } /* If not found getting classloader function symbol. */ if (unlikely(getClassLoaderForInstanceKlass == NULL || getClassLoaderForObjArrayKlass == NULL)) { PRINT_WARN_MSG("Java symbol not found. symbol:\"get_classloader\""); 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 << "Java symbol not found." << " symbol:\"" << arr->vtableSymbol << "\"" << NEWLINE; return false; } /* Search function symbol. */ arr->originalFunc = symFinder->findSymbol(arr->funcSymbol); if (unlikely(arr->originalFunc == NULL)) { PRINT_WARN_MSG_HEADER << "Java symbol not found." << " 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) { SELECT_HOOK_FUNCS(par); /* If failure getting function information. */ if (unlikely(!setupOverrideFunction(par_hook))) { 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) { SELECT_HOOK_FUNCS(parOld); /* If failure getting function information. */ if (unlikely(!setupOverrideFunction(parOld_hook))) { 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) { SELECT_HOOK_FUNCS(cms_new); 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 not exists "CMSBitMap::_bmStartWord" entry in vmstruct. */ if (enableCR6964458) { off_t bmWordSizeOfs = -1; TOffsetNameMap bmWordSizeMap[] = { {"CMSBitMap", "_bmWordSize", &bmWordSizeOfs, NULL}, {NULL, NULL, NULL, NULL} }; vmScanner->GetDataFromVMStructs(bmWordSizeMap); if (likely(bmWordSizeOfs != -1)) { /* * CMSBitMap::_bmStartWord is appeared before _bmWordSize. * See CMSBitMap definition in * hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/ * concurrentMarkSweepGeneration.hpp */ offsetCmsStartWord = bmWordSizeOfs - sizeof(void *); } } /* If failure getting offset. */ if (unlikely(offsetCmsVirtualSpace == -1 || offsetCmsStartWord == -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; } /* 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_startAddr == NULL))){ PRINT_WARN_MSG("Failure getting information form JVM." " info:CMS from:calculate"); return false; } /* 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("Java symbol not found. symbol:\"CollectorState\""); return false; } /* If failure getting function information. */ if (unlikely(!setupOverrideFunction(cms_new_hook))) { PRINT_WARN_MSG("Can't override function. func:CMS_new"); return false; } /* If failure getting function information. */ if (unlikely(!setupOverrideFunction(cms_sweep_hook))) { PRINT_WARN_MSG("Can't override function. func:CMS_sweep"); return false; } BitsPerWordMask = BitsPerWord - 1; return true; } /*! * \brief Setup GC hooking for G1GC * \return Process result. */ bool setupForG1GC(size_t maxMemSize) { SELECT_HOOK_FUNCS(g1); 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; } /* If failure getting function information. */ if (unlikely(!setupOverrideFunction(g1_hook) || !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){ list = parOld_hook; } else if(useCMS){ /* Switch CMS hooking at new generation. */ switchOverrideFunction(cms_new_hook, 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); list = g1_hook; checkObjectMap->clear(); } /* Switch common hooking. */ if (unlikely(!switchOverrideFunction(par_hook, enable))) { PRINT_WARN_MSG("Failure switch function overriding. func:par"); return false; } /* Switch adjust pointer hooking. */ if(!enableCR6964458){ 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, "libjvm.so"))) { throw 1; } /* Cretae VMStruct scanner instance. */ vmScanner = new TVMStructScanner(symFinder); } catch(...) { PRINT_CRIT_MSG("Failure getting symbol information."); jvmti->Deallocate((unsigned char *)libPath); delete symFinder; symFinder = NULL; return false; } jvmti->Deallocate((unsigned char *)libPath); bool result = true; try { /* Setup HotSpot version. */ char *versionStr = NULL; if (unlikely(isError(jvmti, jvmti->GetSystemProperty("java.vm.version", &versionStr)))) { PRINT_CRIT_MSG("Failure getting JVM version."); throw 1; } else { unsigned char major = 0; unsigned char minor = 0; unsigned char build = 0; int result = 0; /* Parse version string. */ result = sscanf(versionStr, "%hhu.%hhu-b%hhu", &major, &minor, &build); /* * We expect to get 3 values (major, minor, build) from sscanf() * at first. */ if(result == 3){ hotSpotVersion = major << 24 | minor << 16 | build; } else{ /* After JDK-8030011: Update Hotspot version string output */ unsigned short micro = 0; result = sscanf(versionStr, "%hhu.%hhu.%hhu", &major, &minor, µ); char *build_str = strrchr(versionStr, 'b'); if(likely(build_str != NULL)){ result += sscanf(build_str, "b%hhu", &build); } /* * We expect to get 4 values (major, minor, micro, build) * from sscanf(). * This versioning equals to JDK version. */ if (unlikely(result != 4)) { PRINT_CRIT_MSG_HEADER << "Unsupported JVM version: " << versionStr << " (" << result << ")" << NEWLINE; jvmti->Deallocate((unsigned char *)versionStr); throw 1; } /* * Latest HS version is "25". * So I add 25 to major. */ major += 25; hotSpotVersion = major << 24 | minor << 16 | micro << 8 | build; } jvmti->Deallocate((unsigned char *)versionStr); } /* * See CR7017732: * Move static fields into Class to prepare for perm gen removal. */ const unsigned int afterCR7017732 = 21 << 24 | 6; enableCR7017732 = (hotSpotVersion >= afterCR7017732); /* * See CR6964458: * Reimplement class meta-data storage to use native memory. */ const unsigned int afterCR6964458 = 25 << 24 | 1; enableCR6964458 = (hotSpotVersion >= afterCR6964458); /* * See CR8000213: * NPG: Should have renamed arrayKlass and typeArrayKlass. */ const unsigned int afterCR8000213 = 25 << 24 | 4; enableCR8000213 = (hotSpotVersion >= afterCR8000213); /* * See JDK-8027746: * Remove do_gen_barrier template parameter in G1ParCopyClosure */ const unsigned int afterCR8027746 = 25 << 24 | 20 << 16 | 2; enableCR8027746 = (hotSpotVersion >= afterCR8027746); /* * See CR8004883: * 8004883: NPG: clean up anonymous class fix */ const unsigned int afterCR8004883 = 25 << 24 | 14; enableCR8004883 = (hotSpotVersion >= afterCR8004883); /* * See CR8003424: * 8003424: Enable Class Data Sharing for CompressedOops */ const unsigned int afterCR8003424 = 25 << 24 | 46; enableCR8003424 = (hotSpotVersion >= afterCR8003424); /* * See CR8015107: * 8015107: NPG: Use consistent naming for metaspace concepts */ const unsigned int afterCR8015107 = 25 << 24 | 51; enableCR8015107 = (hotSpotVersion >= afterCR8015107); /* * See JDK-8049421: * G1 Class Unloading after completing a concurrent mark cycle */ const unsigned int afterCR8049421 = 25 << 24 | 40 << 16 | 5; enableCR8049421 = (hotSpotVersion >= afterCR8049421); /* Search flag symbol in libjvm. */ if (unlikely(!searchCommonFlags())) { PRINT_CRIT_MSG("Failure getting java symbol information."); throw 1; } if(useG1){ /* * See 7046558: G1: concurrent marking optimizations. * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7046558 * http://hg.openjdk.java.net/hsx/hotspot-gc/hotspot/rev/842b840e67db */ const unsigned int afterCR7046558 = 22 << 24 | 3; if (unlikely(hotSpotVersion < afterCR7046558)) { /* Heapstats agent is unsupported G1GC on JDK6. */ PRINT_CRIT_MSG("Sorry, G1GC isn't supported in this version."); PRINT_CRIT_MSG("You should use >= 22.0-b03"); throw 1; } if(arg.TimerInterval > 0){ PRINT_WARN_MSG("Interval SnapShot is not supported with G1GC. Turn off."); arg.TimerInterval = 0; } if(arg.triggerOnDump){ PRINT_WARN_MSG("SnapShot trigger on dump request is not supported with G1GC. Turn off."); arg.triggerOnDump = false; } } /* Search common function symbol in libjvm. */ if (unlikely(!searchCommonFunction())) { PRINT_CRIT_MSG("Failure getting java symbol information."); throw 1; } /* Create pthred key for klassOop. */ if (unlikely(pthread_key_create(&oldKlassOopKey, pThreadKeyDestructor) != 0)) { PRINT_CRIT_MSG("Failure create pthread key."); throw 1; } } catch(...) { /* Deallocate memory. */ delete symFinder; symFinder = NULL; delete vmScanner; vmScanner = NULL; result = false; } return result; } /*! * \brief Finailization of this util. */ void oopUtilFinalize(void) { /* Cleanup. */ if(useG1){ delete checkObjectMap; checkObjectMap = NULL; } delete vmScanner; vmScanner = NULL; delete symFinder; symFinder = NULL; pthread_key_delete(oldKlassOopKey); } /*! * \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) { /* Set function. */ gcCallbackFunc = funcOnGC; cmsCallbackFunc = funcOnCMS; 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(!enableCR6964458){ 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 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) { /* Sanity check. */ if (unlikely(needSnapShot == NULL)) { PRINT_WARN_MSG("Illegal paramter!"); return -1; } static int cmsStateAtStart; *needSnapShot = false; switch (state) { case gcStart: /* Call on JVMTI GC start. */ if (*CMS_collectorState <= CMS_INITIALMARKING) { /* Set stored flag of passed sweep phase. */ *needSnapShot = needSnapShotByCMSPhase; needSnapShotByCMSPhase = false; } else if (*CMS_collectorState == CMS_FINALMARKING) { /* switch hooking for CMS new generation. */ switchOverrideFunction(cms_new_hook, true); } cmsStateAtStart = (*CMS_collectorState); isInvokedParallelGC = false; break; case gcFinish: /* Call on JVMTI GC finished. */ switch (*CMS_collectorState) { case CMS_MARKING: /* CMS marking phase. */ break; case CMS_SWEEPING: /* CMS sweep phase. */ needSnapShotByCMSPhase = true; break; default: /* If called parallel gc. */ if (isInvokedParallelGC) { /* GC invoke by user or service without CMS. */ (*needSnapShot) = true; needSnapShotByCMSPhase = false; break; } } /* If enable cms new gen hook. */ if (cmsStateAtStart == CMS_FINALMARKING) { /* switch hooking for CMS new generation. */ switchOverrideFunction(cms_new_hook, false); } 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."); } return *CMS_collectorState; } /*! * \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); }