|
Lines 1064-1098
Link Here
|
| 1064 |
} |
1064 |
} |
| 1065 |
|
1065 |
|
| 1066 |
SClassFile *pClassWithBasicInstr = new SClassFile(); |
1066 |
SClassFile *pClassWithBasicInstr = new SClassFile(); |
|
|
1067 |
SClassFile classToReturnToJVM; |
| 1068 |
memset(&classToReturnToJVM, 0, sizeof(SClassFile)); |
| 1067 |
|
1069 |
|
| 1068 |
// Apply basic instrumentation to the class file. The memory for the resulting class file |
1070 |
// Apply basic instrumentation to the class file. The memory for the resulting class file |
| 1069 |
// is allocated from the internal JPI heap (using malloc) |
1071 |
// is allocated from the internal JPI heap (using malloc) |
| 1070 |
iRetVal = m_pAdaptor->ModifyClass(classId, classToInstrument, LocalMemAlloc, |
1072 |
TResult modifyClassRes = m_pAdaptor->ModifyClass(classId, classToInstrument, LocalMemAlloc, |
| 1071 |
pClassWithBasicInstr); |
1073 |
pClassWithBasicInstr); |
| 1072 |
|
1074 |
|
| 1073 |
InstrumentationLock(); |
1075 |
InstrumentationLock(); |
| 1074 |
|
1076 |
|
| 1075 |
if (MRTE_SUCCEEDED(iRetVal)) |
1077 |
if (MRTE_SUCCEEDED(modifyClassRes)) |
| 1076 |
{ |
1078 |
{ |
| 1077 |
// Store the instrumented class in the Data Manager. This image will be used |
1079 |
// Store the instrumented class in the Data Manager. This image will be used |
| 1078 |
// for redefining the class in the future (if needed) |
1080 |
// for redefining the class in the future (if needed) |
| 1079 |
iRetVal = m_pDataManager->SetClassFileBuffer(classId, pClassWithBasicInstr); |
1081 |
iRetVal = m_pDataManager->SetClassFileBuffer(classId, pClassWithBasicInstr); |
|
|
1082 |
if (MRTE_SUCCEEDED(iRetVal)) |
| 1083 |
{ |
| 1084 |
// If the class was instrumented, check whether method-level BCI is also needed |
| 1085 |
// and prepare a class buffer for the JVM |
| 1086 |
TResult modifyByteCodesRes; |
| 1087 |
if (m_bInstrGeneratedEventsEnabled) |
| 1088 |
{ |
| 1089 |
modifyByteCodesRes = m_pAdaptor->ModifyByteCodes(classId, *pClassWithBasicInstr, |
| 1090 |
pJVMEvent->u.classLoadHook.pfnAllocate, &classToReturnToJVM); |
| 1091 |
} |
| 1092 |
else |
| 1093 |
{ |
| 1094 |
// Method-level BCI is not needed (events are not enabled) |
| 1095 |
modifyByteCodesRes = MRTE_ERROR_INSTRUMENTATION_NOT_NEEDED; |
| 1096 |
} |
| 1080 |
|
1097 |
|
| 1081 |
// If the class was instrumented, check whether method-level BCI is also needed |
1098 |
// If method-level BCI failed or not needed, use the "basic instrumentation" class image |
| 1082 |
// and prepare a class buffer for the JVM |
1099 |
if (MRTE_FAILED(modifyByteCodesRes)) |
| 1083 |
SClassFile classToReturnToJVM; |
1100 |
{ |
|
|
1101 |
iRetVal = CopyClassFile(&classToReturnToJVM, *pClassWithBasicInstr, |
| 1102 |
pJVMEvent->u.classLoadHook.pfnAllocate); |
| 1103 |
MARTINI_INFORMATIVE2("CJavaInstrumentorManager", 5, false, |
| 1104 |
"Using basic instrumentation for class %u '%s'", |
| 1105 |
(U32)classId, pJVMEvent->u.classLoadHook.szClassName); |
| 1106 |
} |
| 1107 |
else |
| 1108 |
{ |
| 1109 |
MARTINI_INFORMATIVE2("CJavaInstrumentorManager", 5, false, |
| 1110 |
"Using metod-level instrumentation for class %u '%s'", |
| 1111 |
(U32)classId, pJVMEvent->u.classLoadHook.szClassName); |
| 1084 |
|
1112 |
|
| 1085 |
if (m_bInstrGeneratedEventsEnabled) |
1113 |
} |
| 1086 |
{ |
|
|
| 1087 |
iRetVal = m_pAdaptor->ModifyByteCodes(classId, *pClassWithBasicInstr, |
| 1088 |
pJVMEvent->u.classLoadHook.pfnAllocate, &classToReturnToJVM); |
| 1089 |
} |
1114 |
} |
| 1090 |
else |
1115 |
else |
| 1091 |
{ |
1116 |
{ |
| 1092 |
iRetVal = CopyClassFile(&classToReturnToJVM, *pClassWithBasicInstr, |
1117 |
MARTINI_INFORMATIVE2("CJavaInstrumentorManager", 0, false, |
| 1093 |
pJVMEvent->u.classLoadHook.pfnAllocate); |
1118 |
"Unable to store basic image of class '%s' in Data Manager. Class id %u is invalid", |
|
|
1119 |
pJVMEvent->u.classLoadHook.szClassName, (U32)classId); |
| 1094 |
} |
1120 |
} |
| 1095 |
|
1121 |
|
|
|
1122 |
|
| 1096 |
#ifdef DUMP_CLASS |
1123 |
#ifdef DUMP_CLASS |
| 1097 |
char szDumpFileName[1000]; |
1124 |
char szDumpFileName[1000]; |
| 1098 |
sprintf(szDumpFileName, "%s@%p", pJVMEvent->u.classLoadHook.szClassName, |
1125 |
sprintf(szDumpFileName, "%s@%p", pJVMEvent->u.classLoadHook.szClassName, |
|
Lines 1113-1118
Link Here
|
| 1113 |
// Return the instrumented class file to the JVM |
1140 |
// Return the instrumented class file to the JVM |
| 1114 |
*pJVMEvent->u.classLoadHook.ppucNewClassData = classToReturnToJVM.pClassFile; |
1141 |
*pJVMEvent->u.classLoadHook.ppucNewClassData = classToReturnToJVM.pClassFile; |
| 1115 |
*pJVMEvent->u.classLoadHook.pNewClassDataLen = classToReturnToJVM.uiSize; |
1142 |
*pJVMEvent->u.classLoadHook.pNewClassDataLen = classToReturnToJVM.uiSize; |
|
|
1143 |
MARTINI_INFORMATIVE2("CJavaInstrumentorManager", 5, false, |
| 1144 |
"Instrumented class %u '%s' will be returned to JVM", |
| 1145 |
(U32)classId, pJVMEvent->u.classLoadHook.szClassName); |
| 1116 |
} |
1146 |
} |
| 1117 |
else |
1147 |
else |
| 1118 |
{ |
1148 |
{ |
|
Lines 1120-1128
Link Here
|
| 1120 |
SetClassFileNotInstrumented(pJVMEvent); |
1150 |
SetClassFileNotInstrumented(pJVMEvent); |
| 1121 |
if (MRTE_ERROR_FAIL == iRetVal) |
1151 |
if (MRTE_ERROR_FAIL == iRetVal) |
| 1122 |
{ |
1152 |
{ |
| 1123 |
MARTINI_INFORMATIVE1("CJavaInstrumentorManager", 0, false, |
1153 |
MARTINI_INFORMATIVE2("CJavaInstrumentorManager", 0, false, |
| 1124 |
"Class '%s' was not instrumneted due to instrumentation errors", |
1154 |
"Class %u '%s' was not instrumneted due to instrumentation errors", |
| 1125 |
pJVMEvent->u.classLoadHook.szClassName); |
1155 |
(U32)classId, pJVMEvent->u.classLoadHook.szClassName); |
| 1126 |
} |
1156 |
} |
| 1127 |
} |
1157 |
} |
| 1128 |
} |
1158 |
} |
|
Lines 1207-1213
Link Here
|
| 1207 |
return iRes; |
1237 |
return iRes; |
| 1208 |
} |
1238 |
} |
| 1209 |
|
1239 |
|
| 1210 |
// Instrument classes |
1240 |
// Iterate the list of classes, instrument and queue for redefinition only classes |
|
|
1241 |
// that have valid JNI reference and basic instrumentation image |
| 1242 |
|
| 1211 |
TJvmtiClassDefVector vecClassesToRedefine; |
1243 |
TJvmtiClassDefVector vecClassesToRedefine; |
| 1212 |
vecClassesToRedefine.Reserve(pClassIdList->Count()); |
1244 |
vecClassesToRedefine.Reserve(pClassIdList->Count()); |
| 1213 |
|
1245 |
|
|
Lines 1231-1237
Link Here
|
| 1231 |
MARTINI_INFORMATIVE1("CJavaInstrumentorManager", 5, false, |
1263 |
MARTINI_INFORMATIVE1("CJavaInstrumentorManager", 5, false, |
| 1232 |
"Class '%s' added to redefinition list", |
1264 |
"Class '%s' added to redefinition list", |
| 1233 |
strNativeClassName.Get()); |
1265 |
strNativeClassName.Get()); |
| 1234 |
|
1266 |
} |
|
|
1267 |
else if (MRTE_ERROR_INSTRUMENTATION_NOT_NEEDED == iRes |
| 1268 |
|| MRTE_ERROR_UNABLE_TO_INSTRUMENT == iRes) |
| 1269 |
{ |
| 1270 |
MARTINI_INFORMATIVE1("CJavaInstrumentorManager", 5, false, |
| 1271 |
"Class '%s' will not be redefined due to user-defined filters or an internal reason", |
| 1272 |
strNativeClassName.Get()); |
| 1235 |
} |
1273 |
} |
| 1236 |
else |
1274 |
else |
| 1237 |
{ |
1275 |
{ |
|
Lines 1316-1321
Link Here
|
| 1316 |
// adaptor is always used, regardless of the specified group. |
1354 |
// adaptor is always used, regardless of the specified group. |
| 1317 |
// This is OK since this version supports only one adaptor (either Heap or |
1355 |
// This is OK since this version supports only one adaptor (either Heap or |
| 1318 |
// Call Graph) |
1356 |
// Call Graph) |
|
|
1357 |
|
| 1358 |
if (m_pDataManager->AreEventsEnabledForClass(classId) == bEnabled) |
| 1359 |
{ |
| 1360 |
// No need to instrument this class as its events status matches the desired status |
| 1361 |
|
| 1362 |
// NOTE: this implementation assumes that different filters cannot be applied without |
| 1363 |
// disabling events and then enabling them again. |
| 1364 |
return MRTE_ERROR_INSTRUMENTATION_NOT_NEEDED; |
| 1365 |
} |
| 1366 |
|
| 1319 |
SClassFile classWithBasicInstr; |
1367 |
SClassFile classWithBasicInstr; |
| 1320 |
MCString strNativeClassName; |
1368 |
MCString strNativeClassName; |
| 1321 |
TMemoryAllocatorFunc funcAllocator = m_pJVM->GetMemoryAllocator(); |
1369 |
TMemoryAllocatorFunc funcAllocator = m_pJVM->GetMemoryAllocator(); |
|
Lines 1329-1335
Link Here
|
| 1329 |
} |
1377 |
} |
| 1330 |
if (bEnabled) |
1378 |
if (bEnabled) |
| 1331 |
{ |
1379 |
{ |
| 1332 |
// Apply call-graph instrumentation to the class |
1380 |
// Apply method-level instrumentation to the class |
| 1333 |
iRes = m_pAdaptor->ModifyByteCodes(classId, classWithBasicInstr, funcAllocator, |
1381 |
iRes = m_pAdaptor->ModifyByteCodes(classId, classWithBasicInstr, funcAllocator, |
| 1334 |
pInstrumentedClass); |
1382 |
pInstrumentedClass); |
| 1335 |
} |
1383 |
} |
|
Lines 1478-1490
Link Here
|
| 1478 |
assert(classDef.class_bytes); |
1526 |
assert(classDef.class_bytes); |
| 1479 |
pClassRedefQueue->Push(classDef); |
1527 |
pClassRedefQueue->Push(classDef); |
| 1480 |
} |
1528 |
} |
| 1481 |
else |
|
|
| 1482 |
{ |
| 1483 |
if (MRTE_ERROR_INSTRUMENTATION_NOT_NEEDED != iRes |
| 1484 |
&& MRTE_ERROR_UNABLE_TO_INSTRUMENT != iRes) |
| 1485 |
{ |
| 1486 |
iRes = MRTE_ERROR_FAIL; |
| 1487 |
} |
| 1488 |
} |
| 1489 |
return iRes; |
1529 |
return iRes; |
| 1490 |
} |
1530 |
} |