jprofile.c 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315
  1. /* Copyright (C) 2021 Free Software Foundation, Inc.
  2. Contributed by Oracle.
  3. This file is part of GNU Binutils.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3, or (at your option)
  7. any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, 51 Franklin Street - Fifth Floor, Boston,
  15. MA 02110-1301, USA. */
  16. #include "config.h"
  17. #if defined(GPROFNG_JAVA_PROFILING)
  18. #include <alloca.h>
  19. #include <dlfcn.h> /* dlsym() */
  20. #include <sys/stat.h>
  21. #include <fcntl.h>
  22. #include <unistd.h>
  23. #include <errno.h>
  24. #include <sys/param.h> /* MAXPATHLEN */
  25. #include <jni.h>
  26. #include <jvmti.h>
  27. #include "gp-defs.h"
  28. #include "collector.h"
  29. #include "gp-experiment.h"
  30. #include "tsd.h"
  31. /* TprintfT(<level>,...) definitions. Adjust per module as needed */
  32. #define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
  33. #define DBG_LT1 1 // for configuration details, warnings
  34. #define DBG_LT2 2
  35. #define DBG_LT3 3
  36. /* ARCH_STRLEN is defined in dbe, copied here */
  37. #define ARCH_STRLEN(s) ((CALL_UTIL(strlen)(s) + 4 ) & ~0x3)
  38. /* call frame */
  39. typedef struct
  40. {
  41. jint lineno; /* line number in the source file */
  42. jmethodID method_id; /* method executed in this frame */
  43. } JVMPI_CallFrame;
  44. /* call trace */
  45. typedef struct
  46. {
  47. JNIEnv *env_id; /* Env where trace was recorded */
  48. jint num_frames; /* number of frames in this trace */
  49. JVMPI_CallFrame *frames; /* frames */
  50. } JVMPI_CallTrace;
  51. extern void __collector_jprofile_enable_synctrace (void);
  52. int __collector_jprofile_start_attach (void);
  53. static int init_interface (CollectorInterface*);
  54. static int open_experiment (const char *);
  55. static int close_experiment (void);
  56. static int detach_experiment (void);
  57. static void jprof_find_asyncgetcalltrace (void);
  58. static char *apistr = NULL;
  59. static ModuleInterface module_interface = {
  60. "*"SP_JCLASSES_FILE, /* description, exempt from limit */
  61. init_interface, /* initInterface */
  62. open_experiment, /* openExperiment */
  63. NULL, /* startDataCollection */
  64. NULL, /* stopDataCollection */
  65. close_experiment, /* closeExperiment */
  66. detach_experiment /* detachExperiment (fork child) */
  67. };
  68. static CollectorInterface *collector_interface = NULL;
  69. static CollectorModule jprof_hndl = COLLECTOR_MODULE_ERR;
  70. static int __collector_java_attach = 0;
  71. static JavaVM *jvm;
  72. static jmethodID getResource = NULL;
  73. static jmethodID toExternalForm = NULL;
  74. /* Java profiling thread specific data */
  75. typedef struct TSD_Entry
  76. {
  77. JNIEnv *env;
  78. hrtime_t tstamp;
  79. } TSD_Entry;
  80. static unsigned tsd_key = COLLECTOR_TSD_INVALID_KEY;
  81. static collector_mutex_t jclasses_lock = COLLECTOR_MUTEX_INITIALIZER;
  82. static int java_gc_on = 0;
  83. static int java_mem_mode = 0;
  84. static int java_sync_mode = 0;
  85. static int is_hotspot_vm = 0;
  86. static void get_jvm_settings ();
  87. static void rwrite (int fd, const void *buf, size_t nbyte);
  88. static void addToDynamicArchive (const char* name, const unsigned char* class_data, int class_data_len);
  89. static void (*AsyncGetCallTrace)(JVMPI_CallTrace*, jint, ucontext_t*) = NULL;
  90. static void (*collector_heap_record)(int, int, void*) = NULL;
  91. static void (*collector_jsync_begin)() = NULL;
  92. static void (*collector_jsync_end)(hrtime_t, void *) = NULL;
  93. #define gethrtime collector_interface->getHiResTime
  94. /*
  95. * JVMTI declarations
  96. */
  97. static jvmtiEnv *jvmti;
  98. static void jvmti_VMInit (jvmtiEnv*, JNIEnv*, jthread);
  99. static void jvmti_VMDeath (jvmtiEnv*, JNIEnv*);
  100. static void jvmti_ThreadStart (jvmtiEnv*, JNIEnv*, jthread);
  101. static void jvmti_ThreadEnd (jvmtiEnv*, JNIEnv*, jthread);
  102. static void jvmti_CompiledMethodLoad (jvmtiEnv*, jmethodID, jint, const void*,
  103. jint, const jvmtiAddrLocationMap*, const void*);
  104. static void jvmti_CompiledMethodUnload (jvmtiEnv*, jmethodID, const void*);
  105. static void jvmti_DynamicCodeGenerated (jvmtiEnv*, const char*, const void*, jint);
  106. static void jvmti_ClassPrepare (jvmtiEnv*, JNIEnv*, jthread, jclass);
  107. static void jvmti_ClassLoad (jvmtiEnv*, JNIEnv*, jthread, jclass);
  108. //static void jvmti_ClassUnload( jvmtiEnv*, JNIEnv*, jthread, jclass );
  109. static void jvmti_MonitorEnter (jvmtiEnv *, JNIEnv*, jthread, jobject);
  110. static void jvmti_MonitorEntered (jvmtiEnv *, JNIEnv*, jthread, jobject);
  111. #if 0
  112. static void jvmti_MonitorWait (jvmtiEnv *, JNIEnv*, jthread, jobject, jlong);
  113. static void jvmti_MonitorWaited (jvmtiEnv *, JNIEnv*, jthread, jobject, jboolean);
  114. #endif
  115. static void jvmti_ClassFileLoadHook (jvmtiEnv *jvmti_env, JNIEnv* jni_env, jclass class_being_redefined,
  116. jobject loader, const char* name, jobject protection_domain,
  117. jint class_data_len, const unsigned char* class_data,
  118. jint* new_class_data_len, unsigned char** new_class_data);
  119. static void jvmti_GarbageCollectionStart (jvmtiEnv *);
  120. static void
  121. jvmti_GarbageCollectionFinish (jvmtiEnv *);
  122. jvmtiEventCallbacks callbacks = {
  123. jvmti_VMInit, // 50 jvmtiEventVMInit;
  124. jvmti_VMDeath, // 51 jvmtiEventVMDeath;
  125. jvmti_ThreadStart, // 52 jvmtiEventThreadStart;
  126. jvmti_ThreadEnd, // 53 jvmtiEventThreadEnd;
  127. jvmti_ClassFileLoadHook, // 54 jvmtiEventClassFileLoadHook;
  128. jvmti_ClassLoad, // 55 jvmtiEventClassLoad;
  129. jvmti_ClassPrepare, // 56 jvmtiEventClassPrepare;
  130. NULL, // 57 reserved57;
  131. NULL, // 58 jvmtiEventException;
  132. NULL, // 59 jvmtiEventExceptionCatch;
  133. NULL, // 60 jvmtiEventSingleStep;
  134. NULL, // 61 jvmtiEventFramePop;
  135. NULL, // 62 jvmtiEventBreakpoint;
  136. NULL, // 63 jvmtiEventFieldAccess;
  137. NULL, // 64 jvmtiEventFieldModification;
  138. NULL, // 65 jvmtiEventMethodEntry;
  139. NULL, // 66 jvmtiEventMethodExit;
  140. NULL, // 67 jvmtiEventNativeMethodBind;
  141. jvmti_CompiledMethodLoad, // 68 jvmtiEventCompiledMethodLoad;
  142. jvmti_CompiledMethodUnload, // 69 jvmtiEventCompiledMethodUnload;
  143. jvmti_DynamicCodeGenerated, // 70 jvmtiEventDynamicCodeGenerated;
  144. NULL, // 71 jvmtiEventDataDumpRequest;
  145. NULL, // 72 jvmtiEventDataResetRequest;
  146. NULL, /*jvmti_MonitorWait,*/ // 73 jvmtiEventMonitorWait;
  147. NULL, /*jvmti_MonitorWaited,*/ // 74 jvmtiEventMonitorWaited;
  148. jvmti_MonitorEnter, // 75 jvmtiEventMonitorContendedEnter;
  149. jvmti_MonitorEntered, // 76 jvmtiEventMonitorContendedEntered;
  150. NULL, // 77 jvmtiEventMonitorContendedExit;
  151. NULL, // 78 jvmtiEventReserved;
  152. NULL, // 79 jvmtiEventReserved;
  153. NULL, // 80 jvmtiEventReserved;
  154. jvmti_GarbageCollectionStart, // 81 jvmtiEventGarbageCollectionStart;
  155. jvmti_GarbageCollectionFinish, // 82 jvmtiEventGarbageCollectionFinish;
  156. NULL, // 83 jvmtiEventObjectFree;
  157. NULL // 84 jvmtiEventVMObjectAlloc;
  158. };
  159. typedef jint (JNICALL JNI_GetCreatedJavaVMs_t)(JavaVM **, jsize, jsize *);
  160. int
  161. init_interface (CollectorInterface *_collector_interface)
  162. {
  163. collector_interface = _collector_interface;
  164. return COL_ERROR_NONE;
  165. }
  166. static int
  167. open_experiment (const char *exp)
  168. {
  169. if (collector_interface == NULL)
  170. return COL_ERROR_JAVAINIT;
  171. TprintfT (0, "jprofile: open_experiment %s\n", exp);
  172. const char *params = collector_interface->getParams ();
  173. const char *args = params;
  174. while (args)
  175. {
  176. if (__collector_strStartWith (args, "j:") == 0)
  177. {
  178. args += 2;
  179. break;
  180. }
  181. args = CALL_UTIL (strchr)(args, ';');
  182. if (args)
  183. args++;
  184. }
  185. if (args == NULL) /* Java profiling not specified */
  186. return COL_ERROR_JAVAINIT;
  187. tsd_key = collector_interface->createKey (sizeof ( TSD_Entry), NULL, NULL);
  188. if (tsd_key == (unsigned) - 1)
  189. {
  190. TprintfT (0, "jprofile: TSD key create failed.\n");
  191. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">TSD key not created</event>\n",
  192. SP_JCMD_CERROR, COL_ERROR_JAVAINIT);
  193. return COL_ERROR_JAVAINIT;
  194. }
  195. else
  196. Tprintf (DBG_LT2, "jprofile: TSD key create succeeded %d.\n", tsd_key);
  197. args = params;
  198. while (args)
  199. {
  200. if (__collector_strStartWith (args, "H:") == 0)
  201. {
  202. java_mem_mode = 1;
  203. collector_heap_record = (void(*)(int, int, void*))dlsym (RTLD_DEFAULT, "__collector_heap_record");
  204. }
  205. #if 0
  206. else if (__collector_strStartWith (args, "s:") == 0)
  207. {
  208. java_sync_mode = 1;
  209. collector_jsync_begin = (void(*)(hrtime_t, void *))dlsym (RTLD_DEFAULT, "__collector_jsync_begin");
  210. collector_jsync_end = (void(*)(hrtime_t, void *))dlsym (RTLD_DEFAULT, "__collector_jsync_end");
  211. }
  212. #endif
  213. args = CALL_UTIL (strchr)(args, ';');
  214. if (args)
  215. args++;
  216. }
  217. /* synchronization tracing is enabled by the synctrace module, later in initialization */
  218. __collector_java_mode = 1;
  219. java_gc_on = 1;
  220. return COL_ERROR_NONE;
  221. }
  222. /* routine called from the syntrace module to enable Java-API synctrace */
  223. void
  224. __collector_jprofile_enable_synctrace ()
  225. {
  226. if (__collector_java_mode == 0)
  227. {
  228. TprintfT (DBG_LT1, "jprofile: not turning on Java synctrace; Java mode not enabled\n");
  229. return;
  230. }
  231. java_sync_mode = 1;
  232. collector_jsync_begin = (void(*)(hrtime_t, void *))dlsym (RTLD_DEFAULT, "__collector_jsync_begin");
  233. collector_jsync_end = (void(*)(hrtime_t, void *))dlsym (RTLD_DEFAULT, "__collector_jsync_end");
  234. TprintfT (DBG_LT1, "jprofile: turning on Java synctrace, and requesting events\n");
  235. }
  236. int
  237. __collector_jprofile_start_attach (void)
  238. {
  239. if (!__collector_java_mode || __collector_java_asyncgetcalltrace_loaded)
  240. return 0;
  241. void *g_sHandle = RTLD_DEFAULT;
  242. /* Now get the function addresses */
  243. JNI_GetCreatedJavaVMs_t *pfnGetCreatedJavaVMs;
  244. pfnGetCreatedJavaVMs = (JNI_GetCreatedJavaVMs_t *) dlsym (g_sHandle, "JNI_GetCreatedJavaVMs");
  245. if (pfnGetCreatedJavaVMs != NULL)
  246. {
  247. TprintfT (0, "jprofile attach: pfnGetCreatedJavaVMs is detected.\n");
  248. JavaVM * vmBuf[1]; // XXXX only detect on jvm
  249. jsize nVMs = 0;
  250. (*pfnGetCreatedJavaVMs)(vmBuf, 1, &nVMs);
  251. if (vmBuf[0] != NULL && nVMs > 0)
  252. {
  253. jvm = vmBuf[0];
  254. JNIEnv* jni_env = NULL;
  255. (*jvm)->AttachCurrentThread (jvm, (void **) &jni_env, NULL);
  256. Agent_OnLoad (jvm, NULL, NULL);
  257. if ((*jvm)->GetEnv (jvm, (void **) &jni_env, JNI_VERSION_1_2) >= 0 && jni_env && jvmti)
  258. {
  259. jthread thread;
  260. (*jvmti)->GetCurrentThread (jvmti, &thread);
  261. #ifdef DEBUG
  262. collector_thread_t tid;
  263. tid = __collector_thr_self ();
  264. TprintfT (0, "jprofile attach: AttachCurrentThread: thread: %lu jni_env=%p jthread=%p\n",
  265. (unsigned long) tid, jni_env, thread);
  266. #endif /* DEBUG */
  267. jvmti_VMInit (jvmti, jni_env, thread);
  268. (*jvmti)->GenerateEvents (jvmti, JVMTI_EVENT_COMPILED_METHOD_LOAD);
  269. (*jvmti)->GenerateEvents (jvmti, JVMTI_EVENT_DYNAMIC_CODE_GENERATED);
  270. __collector_java_attach = 1;
  271. (*jvm)->DetachCurrentThread (jvm);
  272. }
  273. }
  274. }
  275. return 0;
  276. }
  277. static int
  278. close_experiment (void)
  279. {
  280. /* fixme XXXXX add content here */
  281. /* see detach_experiment() */
  282. __collector_java_mode = 0;
  283. __collector_java_asyncgetcalltrace_loaded = 0;
  284. __collector_java_attach = 0;
  285. java_gc_on = 0;
  286. java_mem_mode = 0;
  287. java_sync_mode = 0;
  288. is_hotspot_vm = 0;
  289. __collector_mutex_init (&jclasses_lock);
  290. tsd_key = COLLECTOR_TSD_INVALID_KEY;
  291. TprintfT (0, "jprofile: experiment closed.\n");
  292. return 0;
  293. }
  294. static int
  295. detach_experiment (void)
  296. /* fork child. Clean up state but don't write to experiment */
  297. {
  298. __collector_java_mode = 0;
  299. java_gc_on = 0;
  300. jvm = NULL;
  301. java_mem_mode = 0;
  302. java_sync_mode = 0;
  303. is_hotspot_vm = 0;
  304. jvmti = NULL;
  305. apistr = NULL;
  306. __collector_mutex_init (&jclasses_lock);
  307. tsd_key = COLLECTOR_TSD_INVALID_KEY;
  308. TprintfT (0, "jprofile: detached from experiment.\n");
  309. return 0;
  310. }
  311. JNIEXPORT jint JNICALL
  312. JVM_OnLoad (JavaVM *vm, char *options, void *reserved)
  313. {
  314. jvmtiError err;
  315. int use_jvmti = 0;
  316. if (!__collector_java_mode)
  317. {
  318. TprintfT (DBG_LT1, "jprofile: JVM_OnLoad invoked with java mode disabled\n");
  319. return JNI_OK;
  320. }
  321. else
  322. TprintfT (DBG_LT1, "jprofile: JVM_OnLoad invoked\n");
  323. jvm = vm;
  324. jvmti = NULL;
  325. if ((*jvm)->GetEnv (jvm, (void **) &jvmti, JVMTI_VERSION_1_0) >= 0 && jvmti)
  326. {
  327. TprintfT (DBG_LT1, "jprofile: JVMTI found\n");
  328. use_jvmti = 1;
  329. }
  330. if (!use_jvmti)
  331. {
  332. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\"/>\n",
  333. SP_JCMD_CERROR, COL_ERROR_JVMNOTSUPP);
  334. return JNI_ERR;
  335. }
  336. else
  337. {
  338. Tprintf (DBG_LT0, "\tjprofile: Initializing for JVMTI\n");
  339. apistr = "JVMTI 1.0";
  340. // setup JVMTI
  341. jvmtiCapabilities cpblts;
  342. err = (*jvmti)->GetPotentialCapabilities (jvmti, &cpblts);
  343. if (err == JVMTI_ERROR_NONE)
  344. {
  345. jvmtiCapabilities cpblts_set;
  346. CALL_UTIL (memset)(&cpblts_set, 0, sizeof (cpblts_set));
  347. /* Add only those capabilities that are among potential ones */
  348. cpblts_set.can_get_source_file_name = cpblts.can_get_source_file_name;
  349. Tprintf (DBG_LT1, "\tjprofile: adding can_get_source_file_name capability: %u\n", cpblts.can_get_source_file_name);
  350. cpblts_set.can_generate_compiled_method_load_events = cpblts.can_generate_compiled_method_load_events;
  351. Tprintf (DBG_LT1, "\tjprofile: adding can_generate_compiled_method_load_events capability: %u\n", cpblts.can_generate_compiled_method_load_events);
  352. if (java_sync_mode)
  353. {
  354. cpblts_set.can_generate_monitor_events = cpblts.can_generate_monitor_events;
  355. Tprintf (DBG_LT1, "\tjprofile: adding can_generate_monitor_events capability: %u\n", cpblts.can_generate_monitor_events);
  356. }
  357. if (java_gc_on)
  358. {
  359. cpblts_set.can_generate_garbage_collection_events = cpblts.can_generate_garbage_collection_events;
  360. Tprintf (DBG_LT1, "\tjprofile: adding can_generate_garbage_collection_events capability: %u\n", cpblts.can_generate_garbage_collection_events);
  361. }
  362. err = (*jvmti)->AddCapabilities (jvmti, &cpblts_set);
  363. Tprintf (DBG_LT1, "\tjprofile: AddCapabilities() returns: %d\n", err);
  364. }
  365. err = (*jvmti)->SetEventCallbacks (jvmti, &callbacks, sizeof ( callbacks));
  366. err = (*jvmti)->SetEventNotificationMode (jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL);
  367. err = (*jvmti)->SetEventNotificationMode (jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL);
  368. err = (*jvmti)->SetEventNotificationMode (jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, NULL);
  369. err = (*jvmti)->SetEventNotificationMode (jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, NULL);
  370. err = (*jvmti)->SetEventNotificationMode (jvmti, JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL);
  371. err = (*jvmti)->SetEventNotificationMode (jvmti, JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_UNLOAD, NULL);
  372. err = (*jvmti)->SetEventNotificationMode (jvmti, JVMTI_ENABLE, JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL);
  373. err = (*jvmti)->SetEventNotificationMode (jvmti, JVMTI_ENABLE, JVMTI_EVENT_THREAD_START, NULL);
  374. err = (*jvmti)->SetEventNotificationMode (jvmti, JVMTI_ENABLE, JVMTI_EVENT_THREAD_END, NULL);
  375. err = (*jvmti)->SetEventNotificationMode (jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
  376. if (java_gc_on)
  377. {
  378. err = (*jvmti)->SetEventNotificationMode (jvmti, JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_START, NULL);
  379. err = (*jvmti)->SetEventNotificationMode (jvmti, JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL);
  380. }
  381. if (java_mem_mode)
  382. {
  383. // err = (*jvmti)->SetEventNotificationMode( jvmti, JVMTI_ENABLE, <no event for heap tracing> , NULL );
  384. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\"/>\n",
  385. SP_JCMD_CWARN, COL_WARN_NO_JAVA_HEAP);
  386. java_mem_mode = 0;
  387. }
  388. if (java_sync_mode)
  389. {
  390. err = (*jvmti)->SetEventNotificationMode (jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_CONTENDED_ENTER, NULL);
  391. err = (*jvmti)->SetEventNotificationMode (jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, NULL);
  392. //err = (*jvmti)->SetEventNotificationMode( jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_WAIT, NULL );
  393. //err = (*jvmti)->SetEventNotificationMode( jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_WAITED, NULL );
  394. }
  395. Tprintf (DBG_LT0, "\tjprofile: JVMTI initialized\n");
  396. }
  397. /* JVM still uses collector API on Solaris to notify us about dynamically generated code.
  398. * If we ask it to generate events we'll end up with duplicate entries in the
  399. * map file.
  400. */
  401. if (use_jvmti)
  402. {
  403. err = (*jvmti)->GenerateEvents (jvmti, JVMTI_EVENT_DYNAMIC_CODE_GENERATED);
  404. err = (*jvmti)->GenerateEvents (jvmti, JVMTI_EVENT_COMPILED_METHOD_LOAD);
  405. }
  406. Tprintf (DBG_LT1, "\tjprofile: JVM_OnLoad ok\n");
  407. return JNI_OK;
  408. }
  409. /* This is currently just a placeholder */
  410. JNIEXPORT jint JNICALL
  411. Agent_OnLoad (JavaVM *vm, char *options, void *reserved)
  412. {
  413. return JVM_OnLoad (vm, options, reserved);
  414. }
  415. static void
  416. rwrite (int fd, const void *buf, size_t nbyte)
  417. {
  418. size_t left = nbyte;
  419. size_t res;
  420. char *ptr = (char*) buf;
  421. while (left > 0)
  422. {
  423. res = CALL_UTIL (write)(fd, ptr, left);
  424. if (res == -1)
  425. {
  426. /* XXX: we can't write this record, we probably
  427. * can't write anything else. Ignore.
  428. */
  429. return;
  430. }
  431. left -= res;
  432. ptr += res;
  433. }
  434. }
  435. void
  436. get_jvm_settings ()
  437. {
  438. jint res;
  439. JNIEnv *jni;
  440. jclass jcls;
  441. jmethodID jmid;
  442. jstring jstrin;
  443. jstring jstrout;
  444. const char *str;
  445. res = (*jvm)->GetEnv (jvm, (void **) &jni, JNI_VERSION_1_2);
  446. if (res < 0)
  447. return;
  448. /* I'm not checking if results are valid as JVM is extremely
  449. * sensitive to exceptions that might occur during these JNI calls
  450. * and will die with a fatal error later anyway.
  451. */
  452. jcls = (*jni)->FindClass (jni, "java/lang/System");
  453. jmid = (*jni)->GetStaticMethodID (jni, jcls, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;");
  454. jstrin = (*jni)->NewStringUTF (jni, "java.class.path");
  455. jstrout = (*jni)->CallStaticObjectMethod (jni, jcls, jmid, jstrin);
  456. str = jstrout ? (*jni)->GetStringUTFChars (jni, jstrout, NULL) : NULL;
  457. if (str)
  458. {
  459. collector_interface->writeLog ("<setting %s=\"%s\"/>\n", SP_JCMD_SRCHPATH, str);
  460. (*jni)->ReleaseStringUTFChars (jni, jstrout, str);
  461. }
  462. jstrin = (*jni)->NewStringUTF (jni, "sun.boot.class.path");
  463. jstrout = (*jni)->CallStaticObjectMethod (jni, jcls, jmid, jstrin);
  464. str = jstrout ? (*jni)->GetStringUTFChars (jni, jstrout, NULL) : NULL;
  465. if (str)
  466. {
  467. collector_interface->writeLog ("<setting %s=\"%s\"/>\n", SP_JCMD_SRCHPATH, str);
  468. (*jni)->ReleaseStringUTFChars (jni, jstrout, str);
  469. }
  470. jstrin = (*jni)->NewStringUTF (jni, "java.home");
  471. jstrout = (*jni)->CallStaticObjectMethod (jni, jcls, jmid, jstrin);
  472. str = jstrout ? (*jni)->GetStringUTFChars (jni, jstrout, NULL) : NULL;
  473. if (str)
  474. {
  475. collector_interface->writeLog ("<setting %s=\"%s/../src.zip\"/>\n", SP_JCMD_SRCHPATH, str);
  476. (*jni)->ReleaseStringUTFChars (jni, jstrout, str);
  477. }
  478. jstrin = (*jni)->NewStringUTF (jni, "java.vm.version");
  479. jstrout = (*jni)->CallStaticObjectMethod (jni, jcls, jmid, jstrin);
  480. str = jstrout ? (*jni)->GetStringUTFChars (jni, jstrout, NULL) : NULL;
  481. if (str)
  482. {
  483. (void) collector_interface->writeLog ("<profile name=\"jprofile\" %s=\"%s\" %s=\"%s\"/>\n",
  484. SP_JCMD_JVERSION, str, "api", apistr != NULL ? apistr : "N/A");
  485. if (__collector_strStartWith (str, "1.4.2_02") < 0)
  486. {
  487. (void) collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\"/>\n",
  488. SP_JCMD_CWARN, COL_WARN_OLDJAVA);
  489. }
  490. (*jni)->ReleaseStringUTFChars (jni, jstrout, str);
  491. }
  492. is_hotspot_vm = 0;
  493. jstrin = (*jni)->NewStringUTF (jni, "sun.management.compiler");
  494. jstrout = (*jni)->CallStaticObjectMethod (jni, jcls, jmid, jstrin);
  495. str = jstrout ? (*jni)->GetStringUTFChars (jni, jstrout, NULL) : NULL;
  496. if (str && __collector_strncmp (str, "HotSpot", 7) == 0)
  497. is_hotspot_vm = 1;
  498. /* Emulate System.setProperty( "collector.init", "true") */
  499. jmid = (*jni)->GetStaticMethodID (jni, jcls, "setProperty",
  500. "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
  501. jstrin = (*jni)->NewStringUTF (jni, "collector.init");
  502. jstrout = (*jni)->NewStringUTF (jni, "true");
  503. (*jni)->CallStaticObjectMethod (jni, jcls, jmid, jstrin, jstrout);
  504. }
  505. /*
  506. * JVMTI code
  507. */
  508. static void
  509. jvmti_VMInit (jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread)
  510. {
  511. jint class_count = 0;
  512. jclass *classes = NULL;
  513. int i;
  514. TprintfT (DBG_LT1, "jprofile: jvmti_VMInit called\n");
  515. get_jvm_settings ();
  516. /* determine loaded classes */
  517. (*jvmti_env)->GetLoadedClasses (jvmti_env, &class_count, &classes);
  518. TprintfT (DBG_LT1, "jprofile: jvmti_VMInit initializing %d classes\n", class_count);
  519. for (i = 0; i < class_count; i++)
  520. {
  521. // PushLocalFrame
  522. jvmti_ClassPrepare (jvmti_env, jni_env, NULL, classes[i]);
  523. // PopLocalFrame
  524. // DeleteLocalRef( classes[i] );
  525. }
  526. (*jvmti_env)->Deallocate (jvmti_env, (unsigned char*) classes);
  527. getResource = (*jni_env)->GetMethodID (jni_env, (*jni_env)->FindClass (jni_env, "java/lang/ClassLoader"), "getResource", "(Ljava/lang/String;)Ljava/net/URL;");
  528. toExternalForm = (*jni_env)->GetMethodID (jni_env, (*jni_env)->FindClass (jni_env, "java/net/URL"), "toExternalForm", "()Ljava/lang/String;");
  529. /* find the stack unwind routine */
  530. jprof_find_asyncgetcalltrace ();
  531. }
  532. static void
  533. jvmti_VMDeath (jvmtiEnv *jvmti_env, JNIEnv* jni_env)
  534. {
  535. __collector_java_mode = 0;
  536. TprintfT (DBG_LT1, "jprofile: jvmti_VMDeath event received\n");
  537. }
  538. static void
  539. jvmti_ThreadStart (jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread)
  540. {
  541. jvmtiError err;
  542. jvmtiThreadInfo t_info;
  543. char *thread_name, *group_name, *parent_name;
  544. hrtime_t hrt;
  545. collector_thread_t tid;
  546. thread_name = group_name = parent_name = NULL;
  547. hrt = gethrtime ();
  548. tid = __collector_thr_self ();
  549. TprintfT (DBG_LT1, "jprofile: jvmti_ThreadStart: thread: %lu jni_env=%p jthread=%p\n",
  550. (unsigned long) tid, jni_env, thread);
  551. err = (*jvmti_env)->GetThreadInfo (jvmti_env, thread, &t_info);
  552. if (err == JVMTI_ERROR_NONE)
  553. {
  554. jvmtiThreadGroupInfo g_info;
  555. thread_name = t_info.name;
  556. if (t_info.thread_group)
  557. {
  558. err = (*jvmti_env)->GetThreadGroupInfo (jvmti_env, t_info.thread_group, &g_info);
  559. if (err == JVMTI_ERROR_NONE)
  560. {
  561. group_name = g_info.name;
  562. if (g_info.parent)
  563. {
  564. jvmtiThreadGroupInfo p_info;
  565. err = (*jvmti_env)->GetThreadGroupInfo (jvmti_env, g_info.parent, &p_info);
  566. if (err == JVMTI_ERROR_NONE)
  567. {
  568. parent_name = p_info.name;
  569. // DeleteLocalRef( p_info.parent );
  570. }
  571. // DeleteLocalRef( g_info.parent );
  572. }
  573. }
  574. }
  575. // DeleteLocalRef( t_info.thread_group );
  576. // DeleteLocalRef( t_info.context_class_loader );
  577. }
  578. if (thread_name == NULL)
  579. thread_name = "";
  580. if (group_name == NULL)
  581. group_name = "";
  582. if (parent_name == NULL)
  583. parent_name = "";
  584. collector_interface->writeLog ("<event kind=\"%s\" tstamp=\"%u.%09u\" name=\"%s\" grpname=\"%s\" prntname=\"%s\" tid=\"%lu\" jthr=\"0x%lx\" jenv=\"0x%lx\"/>\n",
  585. SP_JCMD_JTHRSTART,
  586. (unsigned) (hrt / NANOSEC), (unsigned) (hrt % NANOSEC),
  587. thread_name,
  588. group_name,
  589. parent_name,
  590. (unsigned long) tid,
  591. thread,
  592. jni_env
  593. );
  594. TSD_Entry *tsd = collector_interface->getKey (tsd_key);
  595. if (tsd)
  596. tsd->env = jni_env;
  597. }
  598. static void
  599. jvmti_ThreadEnd (jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread)
  600. {
  601. hrtime_t hrt = gethrtime ();
  602. collector_thread_t tid = __collector_thr_self ();
  603. TprintfT (DBG_LT1, "jprofile: jvmti_ThreadEnd: thread: %lu jni_env=%p jthread=%p\n",
  604. (unsigned long) tid, jni_env, thread);
  605. collector_interface->writeLog ("<event kind=\"%s\" tstamp=\"%u.%09u\" tid=\"%lu\" jthr=\"0x%lx\" jenv=\"0x%lx\"/>\n",
  606. SP_JCMD_JTHREND,
  607. (unsigned) (hrt / NANOSEC), (unsigned) (hrt % NANOSEC),
  608. (unsigned long) tid,
  609. thread,
  610. jni_env
  611. );
  612. TSD_Entry *tsd = collector_interface->getKey (tsd_key);
  613. if (tsd)
  614. tsd->env = NULL;
  615. }
  616. /* The following definitions are borrowed from file jvmticmlr.h, part of jdk7 */
  617. typedef enum
  618. {
  619. JVMTI_CMLR_DUMMY = 1,
  620. JVMTI_CMLR_INLINE_INFO = 2
  621. } jvmtiCMLRKind;
  622. /*
  623. * Record that represents arbitrary information passed through JVMTI
  624. * CompiledMethodLoadEvent void pointer.
  625. */
  626. typedef struct _jvmtiCompiledMethodLoadRecordHeader
  627. {
  628. jvmtiCMLRKind kind; /* id for the kind of info passed in the record */
  629. jint majorinfoversion; /* major and minor info version values. Init'ed */
  630. jint minorinfoversion; /* to current version value in jvmtiExport.cpp. */
  631. struct _jvmtiCompiledMethodLoadRecordHeader* next;
  632. } jvmtiCompiledMethodLoadRecordHeader;
  633. /*
  634. * Record that gives information about the methods on the compile-time
  635. * stack at a specific pc address of a compiled method. Each element in
  636. * the methods array maps to same element in the bcis array.
  637. */
  638. typedef struct _PCStackInfo
  639. {
  640. void* pc; /* the pc address for this compiled method */
  641. jint numstackframes; /* number of methods on the stack */
  642. jmethodID* methods; /* array of numstackframes method ids */
  643. jint* bcis; /* array of numstackframes bytecode indices */
  644. } PCStackInfo;
  645. /*
  646. * Record that contains inlining information for each pc address of
  647. * an nmethod.
  648. */
  649. typedef struct _jvmtiCompiledMethodLoadInlineRecord
  650. {
  651. jvmtiCompiledMethodLoadRecordHeader header; /* common header for casting */
  652. jint numpcs; /* number of pc descriptors in this nmethod */
  653. PCStackInfo* pcinfo; /* array of numpcs pc descriptors */
  654. } jvmtiCompiledMethodLoadInlineRecord;
  655. static void
  656. jvmti_CompiledMethodLoad (jvmtiEnv *jvmti_env, jmethodID method,
  657. jint code_size, const void *code_addr, jint map_length,
  658. const jvmtiAddrLocationMap *map,
  659. const void *compile_info)
  660. {
  661. TprintfT (DBG_LT2, "jprofile: jvmti_CompiledMethodLoad: mid=0x%lx addr=%p sz=0x%lu map=%p info=%p\n",
  662. (unsigned long) method, code_addr, (long) code_size, map, compile_info);
  663. char name[32];
  664. CALL_UTIL (snprintf)(name, sizeof (name), "0x%lx", (unsigned long) method);
  665. /* Parse compile_info to get pc -> bci mapping.
  666. * Don't interpret compile_info from JVMs other than HotSpot.
  667. */
  668. int lntsize = 0;
  669. DT_lineno *lntable = NULL;
  670. if (compile_info != NULL && is_hotspot_vm)
  671. {
  672. Tprintf (DBG_LT2, "Mapping from compile_info:\n");
  673. jvmtiCompiledMethodLoadRecordHeader *currec =
  674. (jvmtiCompiledMethodLoadRecordHeader*) compile_info;
  675. while (currec != NULL)
  676. {
  677. if (currec->kind == JVMTI_CMLR_INLINE_INFO)
  678. {
  679. jvmtiCompiledMethodLoadInlineRecord *inrec =
  680. (jvmtiCompiledMethodLoadInlineRecord*) currec;
  681. if (inrec->numpcs <= 0)
  682. break;
  683. lntsize = inrec->numpcs;
  684. lntable = (DT_lineno*) alloca (lntsize * sizeof (DT_lineno));
  685. PCStackInfo *pcrec = inrec->pcinfo;
  686. DT_lineno *lnorec = lntable;
  687. for (int i = 0; i < lntsize; ++i)
  688. {
  689. for (int j = pcrec->numstackframes - 1; j >= 0; --j)
  690. if (pcrec->methods[j] == method)
  691. {
  692. lnorec->offset = (char*) pcrec->pc - (char*) code_addr;
  693. lnorec->lineno = pcrec->bcis[j];
  694. Tprintf (DBG_LT2, " pc: 0x%lx bci: 0x%lx\n",
  695. (long) lnorec->offset, (long) lnorec->lineno);
  696. ++lnorec;
  697. break;
  698. }
  699. ++pcrec;
  700. }
  701. break;
  702. }
  703. currec = currec->next;
  704. }
  705. }
  706. else if (map != NULL)
  707. {
  708. Tprintf (DBG_LT2, "Mapping from jvmtiAddrLocationMap:\n");
  709. lntsize = map_length;
  710. lntable = (DT_lineno*) alloca (lntsize * sizeof (DT_lineno));
  711. DT_lineno *lnorec = lntable;
  712. for (int i = 0; i < map_length; ++i)
  713. {
  714. lnorec->offset = (char*) map[i].start_address - (char*) code_addr;
  715. lnorec->lineno = (unsigned int) map[i].location;
  716. Tprintf (DBG_LT2, " pc: 0x%lx bci: 0x%lx\n",
  717. (long) lnorec->offset, (long) lnorec->lineno);
  718. ++lnorec;
  719. }
  720. }
  721. __collector_int_func_load (DFUNC_JAVA, name, NULL, (void*) code_addr,
  722. code_size, lntsize, lntable);
  723. }
  724. static void
  725. jvmti_CompiledMethodUnload (jvmtiEnv *jvmti_env, jmethodID method, const void* code_addr)
  726. {
  727. __collector_int_func_unload (DFUNC_API, (void*) code_addr);
  728. }
  729. static void
  730. jvmti_DynamicCodeGenerated (jvmtiEnv *jvmti_env, const char*name, const void *code_addr, jint code_size)
  731. {
  732. __collector_int_func_load (DFUNC_API, (char*) name, NULL, (void*) code_addr,
  733. code_size, 0, NULL);
  734. }
  735. static void
  736. addToDynamicArchive (const char* name, const unsigned char* class_data, int class_data_len)
  737. {
  738. char path[MAXPATHLEN + 1];
  739. mode_t fmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
  740. mode_t dmode = fmode | S_IXUSR | S_IXGRP | S_IXOTH;
  741. if (name == NULL)
  742. name = "";
  743. const char *expdir = collector_interface->getExpDir ();
  744. if (CALL_UTIL (strlen)(expdir) +
  745. CALL_UTIL (strlen)(SP_DYNAMIC_CLASSES) +
  746. CALL_UTIL (strlen)(name) + 8 > sizeof (path))
  747. return;
  748. CALL_UTIL (snprintf)(path, sizeof (path), "%s/%s/%s.class", expdir, SP_DYNAMIC_CLASSES, name);
  749. /* Create all path components step by step starting with SP_DYNAMIC_CLASSES */
  750. char *str = path + CALL_UTIL (strlen)(expdir) + 1 + CALL_UTIL (strlen)(SP_DYNAMIC_CLASSES);
  751. while (str)
  752. {
  753. *str = '\0';
  754. if (CALL_UTIL (mkdir)(path, dmode) != 0)
  755. {
  756. /* Checking for EEXIST is not enough, access() is more reliable */
  757. if (CALL_UTIL (access)(path, F_OK) != 0)
  758. {
  759. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\" ec=\"%d\">%s</event>\n",
  760. SP_JCMD_CERROR, COL_ERROR_MKDIR, errno, path);
  761. return;
  762. }
  763. }
  764. *str++ = '/';
  765. str = CALL_UTIL (strchr)(str, '/');
  766. }
  767. int fd = CALL_UTIL (open)(path, O_WRONLY | O_CREAT | O_TRUNC, fmode);
  768. if (fd < 0)
  769. {
  770. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\" ec=\"%d\">%s</event>\n",
  771. SP_JCMD_CERROR, COL_ERROR_OVWOPEN, errno, path);
  772. return;
  773. }
  774. rwrite (fd, class_data, class_data_len);
  775. CALL_UTIL (close)(fd);
  776. }
  777. static void
  778. jvmti_ClassFileLoadHook (jvmtiEnv *jvmti_env, JNIEnv* jni_env, jclass class_being_redefined,
  779. jobject loader, const char* name, jobject protection_domain, jint class_data_len,
  780. const unsigned char* class_data, jint* new_class_data_len, unsigned char** new_class_data)
  781. {
  782. jclass loaderlass;
  783. int err;
  784. jvmtiPhase phase_ptr;
  785. char *cname = NULL;
  786. (*jvmti_env)->GetPhase (jvmti_env, &phase_ptr);
  787. /* skip non live phases */
  788. if (phase_ptr != JVMTI_PHASE_LIVE)
  789. return;
  790. /* skip system class loaders */
  791. if (!loader)
  792. return;
  793. loaderlass = (*jni_env)->GetObjectClass (jni_env, loader);
  794. err = (*jvmti_env)->GetClassSignature (jvmti_env, loaderlass, &cname, NULL);
  795. if (err != JVMTI_ERROR_NONE || !cname || *cname == (char) 0)
  796. return;
  797. /* skip classes loaded with AppClassLoader (java.class.path) */
  798. if (__collector_strcmp (cname, "Lsun/misc/Launcher$AppClassLoader;") == 0)
  799. return;
  800. addToDynamicArchive (name, class_data, (int) class_data_len);
  801. }
  802. #define NO_CLASS_NAME "<noname>"
  803. #define NO_SOURCE_FILE "<Unknown>"
  804. static void
  805. record_jclass (uint64_t class_id, hrtime_t hrt, const char *cname, const char *sname)
  806. {
  807. size_t clen = ARCH_STRLEN (cname);
  808. size_t slen = ARCH_STRLEN (sname);
  809. size_t sz = sizeof (ARCH_jclass) + clen + slen;
  810. ARCH_jclass *jcls = (ARCH_jclass*) alloca (sz);
  811. jcls->comm.tsize = sz;
  812. jcls->comm.type = ARCH_JCLASS;
  813. jcls->class_id = class_id;
  814. jcls->tstamp = hrt;
  815. char *str = (char*) (jcls + 1);
  816. size_t i = CALL_UTIL (strlcpy)(str, cname, clen);
  817. str += i;
  818. while (i++ < clen)
  819. *str++ = (char) 0; /* pad with 0's */
  820. i = CALL_UTIL (strlcpy)(str, sname, slen);
  821. str += i;
  822. while (i++ < slen)
  823. *str++ = (char) 0; /* pad with 0's */
  824. collector_interface->writeDataPacket (jprof_hndl, (CM_Packet*) jcls);
  825. }
  826. static void
  827. record_jmethod (uint64_t class_id, uint64_t method_id,
  828. const char *mname, const char *msign)
  829. {
  830. size_t mnlen = mname ? ARCH_STRLEN (mname) : 0;
  831. size_t mslen = msign ? ARCH_STRLEN (msign) : 0;
  832. size_t sz = sizeof (ARCH_jmethod) + mnlen + mslen;
  833. ARCH_jmethod *jmth = (ARCH_jmethod*) alloca (sz);
  834. if (jmth == NULL)
  835. {
  836. TprintfT (DBG_LT1, "jprofile: record_jmethod ERROR: failed to alloca(%ld)\n", (long) sz);
  837. return;
  838. }
  839. jmth->comm.tsize = sz;
  840. jmth->comm.type = ARCH_JMETHOD;
  841. jmth->class_id = class_id;
  842. jmth->method_id = method_id;
  843. char *str = (char*) (jmth + 1);
  844. if (mname)
  845. {
  846. size_t i = CALL_UTIL (strlcpy)(str, mname, mnlen);
  847. str += i;
  848. while (i++ < mnlen)
  849. *str++ = (char) 0; /* pad with 0's */
  850. }
  851. if (msign)
  852. {
  853. size_t i = CALL_UTIL (strlcpy)(str, msign, mslen);
  854. str += i;
  855. while (i++ < mslen)
  856. *str++ = (char) 0; /* pad with 0's */
  857. }
  858. collector_interface->writeDataPacket (jprof_hndl, (CM_Packet*) jmth);
  859. }
  860. static void
  861. jvmti_ClassPrepare (jvmtiEnv *jvmti_env, JNIEnv* jni_env,
  862. jthread thread, jclass klass)
  863. {
  864. hrtime_t hrt;
  865. jint mnum;
  866. jmethodID *mptr;
  867. char *cname, *sname;
  868. char *str1 = NULL;
  869. int err = (*jvmti_env)->GetClassSignature (jvmti_env, klass, &str1, NULL);
  870. if (err != JVMTI_ERROR_NONE || str1 == NULL || *str1 == (char) 0)
  871. cname = NO_CLASS_NAME;
  872. else
  873. cname = str1;
  874. if (*cname != 'L')
  875. {
  876. DprintfT (SP_DUMP_JAVA | SP_DUMP_TIME, "jvmti_ClassPrepare: GetClassSignature failed. err=%d cname=%s\n", err, cname);
  877. return;
  878. }
  879. char *str2 = NULL;
  880. err = (*jvmti_env)->GetSourceFileName (jvmti_env, klass, &str2);
  881. if (err != JVMTI_ERROR_NONE || str2 == NULL || *str2 == (char) 0)
  882. sname = NO_SOURCE_FILE;
  883. else
  884. sname = str2;
  885. DprintfT (SP_DUMP_JAVA | SP_DUMP_TIME, "jvmti_ClassPrepare: cname=%s sname=%s\n", STR (cname), STR (sname));
  886. /* Lock the whole file */
  887. __collector_mutex_lock (&jclasses_lock);
  888. hrt = gethrtime ();
  889. record_jclass ((unsigned long) klass, hrt, cname, sname);
  890. (*jvmti_env)->Deallocate (jvmti_env, (unsigned char *) str1);
  891. (*jvmti_env)->Deallocate (jvmti_env, (unsigned char *) str2);
  892. err = (*jvmti_env)->GetClassMethods (jvmti_env, klass, &mnum, &mptr);
  893. if (err == JVMTI_ERROR_NONE)
  894. {
  895. for (int i = 0; i < mnum; i++)
  896. {
  897. char *mname, *msign;
  898. err = (*jvmti_env)->GetMethodName (jvmti_env, mptr[i], &mname, &msign, NULL);
  899. if (err != JVMTI_ERROR_NONE)
  900. continue;
  901. record_jmethod ((unsigned long) klass, (unsigned long) mptr[i], mname, msign);
  902. // DeleteLocalRef( mptr[i] );
  903. }
  904. (*jvmti_env)->Deallocate (jvmti_env, (unsigned char*) mptr);
  905. }
  906. /* Unlock the file */
  907. __collector_mutex_unlock (&jclasses_lock);
  908. }
  909. /*
  910. * The CLASS_LOAD event is enabled to enable AsyncGetCallTrace
  911. */
  912. static void
  913. jvmti_ClassLoad (jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jclass klass)
  914. {
  915. char *cname;
  916. char *str1 = NULL;
  917. int err = (*jvmti_env)->GetClassSignature (jvmti_env, klass, &str1, NULL);
  918. if (err != JVMTI_ERROR_NONE || str1 == NULL || *str1 == (char) 0)
  919. cname = NO_CLASS_NAME;
  920. else
  921. cname = str1;
  922. jstring str = NULL;
  923. const char* resourceName;
  924. jobject classLoader = NULL;
  925. err = (*jvmti)->GetClassLoader (jvmti, klass, &classLoader);
  926. DprintfT (SP_DUMP_JAVA | SP_DUMP_TIME, "jprofile: jvmti_ClassLoad err=%d cname=%s\n", err, STR (cname));
  927. if (err == 0)
  928. {
  929. if (classLoader == NULL)
  930. {
  931. // bootstrap class loader
  932. resourceName = "";
  933. }
  934. else
  935. {
  936. char* name = (char *) alloca ((CALL_UTIL (strlen)(str1) + 32) * sizeof (char));
  937. CALL_UTIL (strlcpy)(name, str1 + 1, CALL_UTIL (strlen)(str1));
  938. name[CALL_UTIL (strlen)(name) - 1] = '\0'; // remove the last ';'
  939. char* p;
  940. for (p = name; *p != '\0'; p++)
  941. if (*p == '.')
  942. *p = '/';
  943. CALL_UTIL (strlcat)(name, ".class", CALL_UTIL (strlen)(name) + CALL_UTIL (strlen)(".class") + 1);
  944. if (getResource == NULL || toExternalForm == NULL)
  945. {
  946. resourceName = "";
  947. DprintfT (SP_DUMP_JAVA | SP_DUMP_TIME, "jvmti_ClassLoad: class %s failed to get path with method missing\n", STR (cname));
  948. }
  949. else
  950. {
  951. jobject url = (*jni_env)->CallObjectMethod (jni_env, classLoader, getResource, (*jni_env)->NewStringUTF (jni_env, name));
  952. if (url == NULL)
  953. {
  954. resourceName = "";
  955. DprintfT (SP_DUMP_JAVA | SP_DUMP_TIME, "jvmti_ClassLoad: class %s failed to get path\n", STR (cname));
  956. }
  957. else
  958. {
  959. str = (jstring) (*jni_env)->CallObjectMethod (jni_env, url, toExternalForm);
  960. resourceName = (*jni_env)->GetStringUTFChars (jni_env, str, NULL);
  961. DprintfT (SP_DUMP_JAVA | SP_DUMP_TIME, "jvmti_ClassLoad: ARCH_JCLASS_LOCATION(Ox%x) class_id=0x%lx className='%s' fileName '%s'\n",
  962. (int) ARCH_JCLASS_LOCATION, (unsigned long) klass, STR (cname), STR (resourceName));
  963. size_t clen = ARCH_STRLEN (cname);
  964. size_t slen = ARCH_STRLEN (resourceName);
  965. size_t sz = sizeof (ARCH_jclass) + clen + slen;
  966. ARCH_jclass_location *jcls = (ARCH_jclass_location*) alloca (sz);
  967. jcls->comm.tsize = sz;
  968. jcls->comm.type = ARCH_JCLASS_LOCATION;
  969. jcls->class_id = (unsigned long) klass;
  970. char *str = (char*) (jcls + 1);
  971. size_t i = CALL_UTIL (strlcpy)(str, cname, clen);
  972. str += i;
  973. while (i++ < clen)
  974. {
  975. *str++ = (char) 0; /* pad with 0's */
  976. }
  977. i = CALL_UTIL (strlcpy)(str, resourceName, slen);
  978. str += i;
  979. while (i++ < slen)
  980. {
  981. *str++ = (char) 0; /* pad with 0's */
  982. }
  983. /* Lock the whole file */
  984. __collector_mutex_lock (&jclasses_lock);
  985. collector_interface->writeDataPacket (jprof_hndl, (CM_Packet*) jcls);
  986. /* Unlock the file */
  987. __collector_mutex_unlock (&jclasses_lock);
  988. }
  989. }
  990. }
  991. }
  992. }
  993. static void
  994. jvmti_MonitorEnter (jvmtiEnv *jvmti_env, JNIEnv* jni_env,
  995. jthread thread, jobject object)
  996. {
  997. if (collector_jsync_begin)
  998. collector_jsync_begin ();
  999. TSD_Entry *tsd = collector_interface->getKey (tsd_key);
  1000. if (tsd == NULL)
  1001. return;
  1002. tsd->tstamp = gethrtime ();
  1003. }
  1004. static void
  1005. jvmti_MonitorEntered (jvmtiEnv *jvmti_env, JNIEnv* jni_env,
  1006. jthread thread, jobject object)
  1007. {
  1008. TSD_Entry *tsd = collector_interface->getKey (tsd_key);
  1009. if (tsd == NULL)
  1010. return;
  1011. if (collector_jsync_end)
  1012. collector_jsync_end (tsd->tstamp, object);
  1013. }
  1014. static void
  1015. jvmti_GarbageCollectionStart (jvmtiEnv *jvmti_env)
  1016. {
  1017. hrtime_t hrt = gethrtime ();
  1018. collector_interface->writeLog ("<event kind=\"%s\" tstamp=\"%u.%09u\"/>\n",
  1019. SP_JCMD_GCSTART,
  1020. (unsigned) (hrt / NANOSEC), (unsigned) (hrt % NANOSEC)
  1021. );
  1022. TprintfT (DBG_LT1, "jprofile: jvmti_GarbageCollectionStart.\n");
  1023. }
  1024. static void
  1025. jvmti_GarbageCollectionFinish (jvmtiEnv *jvmti_env)
  1026. {
  1027. hrtime_t hrt = gethrtime ();
  1028. collector_interface->writeLog ("<event kind=\"%s\" tstamp=\"%u.%09u\"/>\n",
  1029. SP_JCMD_GCEND,
  1030. (unsigned) (hrt / NANOSEC), (unsigned) (hrt % NANOSEC)
  1031. );
  1032. TprintfT (DBG_LT1, "jprofile: jvmti_GarbageCollectionFinish.\n");
  1033. }
  1034. #if 0
  1035. static void
  1036. jvmti_MonitorWait (jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
  1037. jobject object, jlong timed_out)
  1038. {
  1039. if (collector_sync_begin)
  1040. collector_sync_begin ();
  1041. TSD_Entry *tsd = collector_interface->getKey (tsd_key);
  1042. if (tsd == NULL)
  1043. return;
  1044. tsd->tstamp = gethrtime ();
  1045. }
  1046. static void
  1047. jvmti_MonitorWaited (jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
  1048. jobject object, jboolean timed_out)
  1049. {
  1050. TSD_Entry *tsd = collector_interface->getKey (tsd_key);
  1051. if (tsd == NULL)
  1052. return;
  1053. if (collector_sync_end)
  1054. collector_sync_end (tsd->tstamp, object);
  1055. }
  1056. #endif
  1057. static void
  1058. jprof_find_asyncgetcalltrace ()
  1059. {
  1060. void *jvmhandle;
  1061. if (__collector_VM_ReadByteInstruction == NULL)
  1062. __collector_VM_ReadByteInstruction = (int(*)()) dlsym (RTLD_DEFAULT, "Async_VM_ReadByteInstruction");
  1063. /* look for stack unwind function using default path */
  1064. AsyncGetCallTrace = (void (*)(JVMPI_CallTrace*, jint, ucontext_t*))
  1065. dlsym (RTLD_DEFAULT, "AsyncGetCallTrace");
  1066. if (AsyncGetCallTrace != NULL)
  1067. {
  1068. __collector_java_asyncgetcalltrace_loaded = 1;
  1069. TprintfT (DBG_LT1, "jprofile: AsyncGetCallTrace found with RTLD_DEFAULT\n");
  1070. }
  1071. else
  1072. {
  1073. /* not found there, find libjvm.so, and ask again */
  1074. jvmhandle = dlopen ("libjvm.so", RTLD_LAZY | RTLD_NOLOAD);
  1075. if (jvmhandle != NULL)
  1076. {
  1077. AsyncGetCallTrace = (void (*)(JVMPI_CallTrace*, jint, ucontext_t*))
  1078. dlsym (jvmhandle, "AsyncGetCallTrace");
  1079. }
  1080. }
  1081. if (AsyncGetCallTrace == NULL)
  1082. {
  1083. /* we could not find it -- write collector error */
  1084. TprintfT (0, "jprofile: ERROR -- AsyncGetCallTrace not found in address space\n");
  1085. char *err = dlerror ();
  1086. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
  1087. SP_JCMD_CERROR, COL_ERROR_JVMNOJSTACK, err ? err : "");
  1088. __collector_java_mode = 0;
  1089. }
  1090. else
  1091. {
  1092. __collector_java_asyncgetcalltrace_loaded = 1;
  1093. TprintfT (DBG_LT1, "jprofile: AsyncGetCallTrace initialized in jprof_jvmpi_init_done_event\n");
  1094. }
  1095. }
  1096. int
  1097. __collector_ext_jstack_unwind (char *ptr, int sz, ucontext_t *uc)
  1098. {
  1099. if (AsyncGetCallTrace == NULL)
  1100. {
  1101. TprintfT (DBG_LT0, "jprofile: __collector_ext_jstack_unwind: AsyncGetCallTrace is NULL\n");
  1102. return 0;
  1103. }
  1104. TSD_Entry *tsd = collector_interface->getKey (tsd_key);
  1105. if (tsd == NULL)
  1106. {
  1107. TprintfT (DBG_LT3, "jprofile: __collector_ext_jstack_unwind: tsd is NULL\n");
  1108. return 0;
  1109. }
  1110. if (__collector_java_attach && tsd->env == NULL && jvmti != NULL && jvm != NULL)
  1111. {
  1112. TprintfT (DBG_LT3, "jprofile: __collector_ext_jstack_unwind: tsd->env is NULL under attach\n");
  1113. JNIEnv* jni_env = NULL;
  1114. (*jvm)->GetEnv (jvm, (void **) &jni_env, JNI_VERSION_1_2);
  1115. tsd->env = jni_env;
  1116. }
  1117. if (tsd->env == NULL)
  1118. {
  1119. TprintfT (DBG_LT3, "jprofile: __collector_ext_jstack_unwind: tsd->env is NULL\n");
  1120. return 0;
  1121. }
  1122. /* skip the Java stack whenever another signal handler is present */
  1123. if (uc->uc_link)
  1124. {
  1125. TprintfT (DBG_LT3, "jprofile: __collector_ext_jstack_unwind: uc->uc_link is non-NULL\n");
  1126. return 0;
  1127. }
  1128. /* we don't expect Java frames in signal handlers, so
  1129. * unroll the list of saved contexts to the topmost one
  1130. */
  1131. while (uc->uc_link)
  1132. uc = uc->uc_link;
  1133. Java_info *jinfo = (Java_info*) ptr;
  1134. jinfo->kind = JAVA_INFO;
  1135. jinfo->hsize = sizeof (Java_info);
  1136. ptr += sizeof (Java_info);
  1137. sz -= sizeof (Java_info);
  1138. JVMPI_CallTrace jtrace;
  1139. jtrace.env_id = tsd->env;
  1140. jtrace.frames = (JVMPI_CallFrame*) ptr;
  1141. /* nframes is how many frames we have room for */
  1142. jint nframes = sz / sizeof (JVMPI_CallFrame);
  1143. #if WSIZE(64)
  1144. /* bug 6909545: garbage in 64-bit JAVA_INFO */
  1145. CALL_UTIL (memset)(jtrace.frames, 0, nframes * sizeof (JVMPI_CallFrame));
  1146. #endif
  1147. #if ARCH(SPARC)
  1148. // 21328946 JDK bug 8129933 causes <no java callstack recorded> on sparc-Linux
  1149. // convert from ucontext_t to sigcontext
  1150. struct sigcontext sctx;
  1151. sctx.sigc_regs.tpc = uc->uc_mcontext.mc_gregs[MC_PC];
  1152. __collector_memcpy (sctx.sigc_regs.u_regs, &uc->uc_mcontext.mc_gregs[3], sizeof (sctx.sigc_regs.u_regs));
  1153. uc = (ucontext_t *) (&sctx);
  1154. #endif /* SPARC */
  1155. AsyncGetCallTrace (&jtrace, nframes, uc);
  1156. if (jtrace.num_frames == nframes)
  1157. {
  1158. JVMPI_CallFrame *last = &jtrace.frames[nframes - 1];
  1159. last->method_id = (jmethodID) SP_TRUNC_STACK_MARKER;
  1160. last->lineno = 0;
  1161. }
  1162. /* nframes is how many frames we actually got */
  1163. nframes = jtrace.num_frames;
  1164. TprintfT (DBG_LT3, "jprofile: __collector_ext_jstack_unwind: AsyncGetCallTrace jtrace.numframes = %d\n", nframes);
  1165. if (nframes <= 0)
  1166. {
  1167. /* negative values are error codes */
  1168. TprintfT (0, "jprofile: __collector_ext_jstack_unwind: AsyncGetCallTrace returned error: jtrace.numframes = %d\n", nframes);
  1169. nframes = 1;
  1170. JVMPI_CallFrame *err = (JVMPI_CallFrame*) ptr;
  1171. err->lineno = jtrace.num_frames; // bci = error code
  1172. err->method_id = 0; // artificial method id
  1173. }
  1174. jinfo->hsize += nframes * sizeof (JVMPI_CallFrame);
  1175. return jinfo->hsize;
  1176. }
  1177. /*
  1178. * Collector Java API implementation
  1179. */
  1180. void
  1181. Java_com_sun_forte_st_collector_CollectorAPI__1sample(JNIEnv *jEnv, jclass jCls, jstring jName)
  1182. {
  1183. JNIEnv *jni;
  1184. jint res = (*jvm)->GetEnv (jvm, (void **) &jni, JNI_VERSION_1_2);
  1185. if (res < 0)
  1186. return;
  1187. const char *name = jName ? (*jni)->GetStringUTFChars (jni, jName, NULL) : NULL;
  1188. __collector_sample ((char*) name);
  1189. }
  1190. void
  1191. Java_com_sun_forte_st_collector_CollectorAPI__1pause(JNIEnv *jEnv, jclass jCls)
  1192. {
  1193. __collector_pause_m ("JAPI");
  1194. }
  1195. void
  1196. Java_com_sun_forte_st_collector_CollectorAPI__1resume(JNIEnv *jEnv, jclass jCls)
  1197. {
  1198. __collector_resume ();
  1199. }
  1200. void
  1201. Java_com_sun_forte_st_collector_CollectorAPI__1terminate(JNIEnv *jEnv, jclass jCls)
  1202. {
  1203. __collector_terminate_expt ();
  1204. }
  1205. #endif /* GPROFNG_JAVA_PROFILING */
  1206. static void init_module () __attribute__ ((constructor));
  1207. static void
  1208. init_module ()
  1209. {
  1210. #if defined(GPROFNG_JAVA_PROFILING)
  1211. __collector_dlsym_guard = 1;
  1212. RegModuleFunc reg_module = (RegModuleFunc) dlsym (RTLD_DEFAULT, "__collector_register_module");
  1213. __collector_dlsym_guard = 0;
  1214. if (reg_module)
  1215. {
  1216. jprof_hndl = reg_module (&module_interface);
  1217. TprintfT (0, "jprofile: init_module.\n");
  1218. }
  1219. #endif /* GPROFNG_JAVA_PROFILING */
  1220. }
  1221. int __collector_java_mode = 0;
  1222. int __collector_java_asyncgetcalltrace_loaded = 0;