00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "xdprof.h"
00033
00034
00036 bool HotSpot = false;
00037
00039 static char* const NullCharPointer = "null";
00040
00045 static inline char* FixNull(char* c)
00046 {
00047 return (c == null) ? NullCharPointer : c;
00048 }
00049
00050
00051 ThreadInfo::ThreadInfo(char *thread_name, char *group_name, char *parent_name, jobjectID thread_id, JNIEnv *thread_env_id)
00052 : m_thread_name(FixNull(thread_name)),
00053 m_thread_id(thread_id),
00054 m_thread_env_id(*thread_env_id),
00055 m_started(0)
00056 {
00057 _snprintf(m_printable, 512, "%s\n%s\n%s\n", FixNull(thread_name), FixNull(group_name), FixNull(parent_name));
00058 }
00059
00060 ThreadInfo::ThreadInfo(const ThreadInfo & ci)
00061 {
00062 strncpy(m_printable, ci.m_printable, 512);
00063 m_thread_name = ci.m_thread_name;
00064 }
00065
00066 void ThreadInfo::setStarted(unsigned long started) const
00067 {
00068 m_started = started;
00069 }
00070
00071 inline unsigned long ThreadInfo::getStarted() const
00072 {
00073 return m_started;
00074 }
00075
00076 inline const char* ThreadInfo::getShortInfo() const
00077 {
00078 return m_printable;
00079 }
00080
00081 string ThreadInfo::getThreadName() const
00082 {
00083 return m_thread_name;
00084 }
00085
00086
00087 ClassInfo::ClassInfo(const ClassInfo & ci)
00088 {
00089 m_class_name = ci.m_class_name;
00090 m_source_name = ci.m_source_name;
00091 m_class_id = ci.m_class_id;
00092
00093 if (ci.m_printable == null)
00094 {
00095 m_printable = null;
00096 }
00097 else
00098 {
00099 m_printable = new char[512];
00100 strncpy(m_printable, ci.m_printable, 512);
00101 }
00102 }
00103
00104 ClassInfo::~ClassInfo()
00105 {
00106 delete[] m_printable ;
00107 }
00108
00109 ClassInfo::ClassInfo( char * class_name, char * source_name, jclassID class_id)
00110 {
00111 if (!HotSpot)
00112 {
00113 m_class_name = class_name;
00114 m_source_name = source_name;
00115 }
00116 else
00117 {
00118
00119 m_class_name = new char[512];
00120 strncpy(m_class_name, class_name, 512);
00121
00122 if (source_name != null)
00123 {
00124 m_source_name = new char[512];
00125 strncpy(m_source_name, source_name, 512);
00126 }
00127 else
00128 m_source_name = null;
00129
00130 }
00131 m_class_id = class_id;
00132 m_printable = null;
00133 }
00134
00135 const char * ClassInfo::getShortInfo() const
00136 {
00137 if (m_printable != null)
00138 return m_printable;
00139 m_printable = new char[512];
00140 _snprintf(m_printable, 512, "%08X %s %s", m_class_id, m_class_name, (m_source_name == null) ? "unknown" : m_source_name);
00141 return m_printable;
00142 }
00143
00144 MethodInfo::MethodInfo(const MethodInfo & mi)
00145 {
00146 m_class_id = mi.m_class_id;
00147 m_method_id = mi.m_method_id;
00148 m_method_name = mi.m_method_name;
00149 m_method_signature = mi.m_method_signature;
00150 m_short_string = null;
00151 }
00152
00153 MethodInfo::~MethodInfo()
00154 {
00155 cout << "~MI " << m_method_id << endl;
00156 delete[] m_short_string;
00157 }
00158
00159
00160
00161 inline const char* MethodInfo::getShortInfo() const
00162 {
00163 if (m_short_string != null)
00164 return m_short_string;
00165
00166 m_short_string = new char[512];
00167 _snprintf(m_short_string, 512, "%08X %08X %s %s\0", m_class_id, m_method_id, m_method_name, m_method_signature);
00168 return m_short_string;
00169 }
00170 jobjectID MethodInfo::getClassID() const
00171 {
00172 return m_class_id;
00173 }
00174
00175 MethodInfo::MethodInfo(
00176 char * method_name,
00177 char * method_signature,
00178 jint ,
00179 jint ,
00180 jmethodID method_id,
00181 jobjectID class_id)
00182 {
00183 m_class_id = class_id;
00184 m_method_id = method_id;
00185 m_short_string = null;
00186
00187 if (!HotSpot)
00188 {
00189 m_method_name = method_name;
00190 m_method_signature = method_signature;
00191 }
00192 else
00193 {
00194 m_method_name = new char[512];
00195 m_method_signature = new char[512];
00196 strncpy(m_method_name, method_name, 512);
00197 strncpy(m_method_signature, method_signature , 512);
00198 }
00199
00200
00201 }
00202
00203
00204
00205 void ThreadDump(const string& info, ThreadID caller)
00206 {
00207 ostringstream output;
00208
00209 Lock(threads_lock);
00210 Lock(methods_lock);
00211 Lock(output_lock);
00212
00213 if (ShutdownRequested)
00214 {
00215 unsafe_debug("shutdown in ", "ThreadDump");
00216 Unlock(output_lock);
00217 Unlock(methods_lock);
00218 Unlock(threads_lock);
00219 return;
00220
00221 }
00222
00223
00224 CALL(DisableGC());
00225
00226 ThreadMap::iterator t;
00227 set<ThreadID> SuspendedThreads;
00228
00229 const char Endl = '\n';
00230
00231
00232 for (t = Threads.begin(); t != Threads.end(); ++t)
00233 {
00234 ThreadID tid = t->first;
00235 jlong status = CALL(GetThreadStatus)(tid);
00236 if ((tid != caller) &&
00237 (
00238 ((status & (~JVMPI_THREAD_INTERRUPTED)) == JVMPI_THREAD_RUNNABLE)
00239 || HotSpot
00240 )
00241 )
00242 {
00243 CALL(SuspendThread)(tid);
00244 SuspendedThreads.insert(tid);
00245 unsafe_debug("Suspended ", tid);
00246 }
00247 else
00248 {
00249 unsafe_debug(tid, (long)status);
00250 }
00251 }
00252
00253 unsafe_debug("#threads ", Threads.size());
00254 output << "// start_message; num threads: " << Threads.size() << Endl;
00255 output << Threads.size() << Endl;
00256 const int number_of_frames = 100;
00257
00258 MethodSet methods_to_send;
00259 JVMPI_CallTrace trace;
00260 JVMPI_CallFrame tframes[number_of_frames];
00261 const JVMPI_CallFrame* f;
00262 for (t = Threads.begin(); t != Threads.end(); ++t)
00263 {
00264 const ThreadInfo& ti = t->second;
00265
00266 output << "// start_thread " << t->first << Endl;
00267 output << t->first << Endl;
00268
00269 jint thread_status = CALL(GetThreadStatus)(t->first);
00270 output << ti.getShortInfo();
00271 output << ti.getStarted() << Endl;
00272 output << thread_status << Endl;
00273
00274
00275
00276 trace.frames = tframes;
00277 trace.env_id = t->first;
00278
00279 CALL(GetCallTrace)(&trace, number_of_frames);
00280
00281 unsafe_debug("num frames: ", trace.num_frames);
00282
00283 output << "// num frames = " << trace.num_frames << Endl;
00284 output << trace.num_frames << Endl;
00285
00286
00287 for (int i = 0; i < trace.num_frames; i++)
00288 {
00289
00290 f = &trace.frames[i];
00291
00292 output << f->method_id << ' ' << f->lineno << Endl;
00293
00294 methods_to_send.insert(f->method_id);
00295 }
00296
00297 }
00298
00299 output << "// sending methods now, count=" << methods_to_send.size() << Endl;
00300 output << methods_to_send.size() << Endl;
00301 ClassSet classes_to_send;
00302
00303 const MethodInfo * the_method;
00304
00305 MethodMap::iterator m;
00306 const MethodMap::iterator m_end = Methods.end();
00307 MethodMap::iterator mc_end = MethodCache.end();
00308 const MethodSet::iterator mse = methods_to_send.end();
00309 for(MethodSet::iterator mi = methods_to_send.begin(); mi != mse; ++mi)
00310 {
00311
00312 m = MethodCache.find(*mi);
00313 if (m == mc_end)
00314 {
00315
00316 m = Methods.find(*mi);
00317
00318
00319 if (m == m_end )
00320 {
00321 jclassID cid = CALL(GetMethodClass(*mi));
00322 unsafe_debug("Couldn't find ", *mi, cid);
00323 unsafe_debug("perf Methods = ", Methods.size());
00324 output << ends;
00325
00326
00327 assert(m != Methods.end());
00328 CALL(EnableGC());
00329 Unlock(output_lock);
00330 Unlock(methods_lock);
00331 Unlock(threads_lock);
00332 return;
00333 }
00334
00335 MethodCache.insert(make_pair(*mi, m->second));
00336 mc_end = MethodCache.end();
00337 }
00338
00339 assert(m != Methods.end());
00340 the_method = m->second;
00341
00342
00343 output << the_method->getShortInfo() << Endl;
00344 unsafe_debug(the_method->getClassID(), the_method->getShortInfo());
00345 classes_to_send.insert(the_method->getClassID());
00346 }
00347
00348 output << "// sending classes now, count=" << classes_to_send.size() << Endl;
00349 output << classes_to_send.size() << Endl;
00350 const ClassInfoMap::iterator end = ClassCache.end();
00351 ClassInfoMap::iterator c;
00352 const ClassSet::iterator cse = classes_to_send.end();
00353 for (ClassSet::iterator ci = classes_to_send.begin(); ci != cse; ++ci)
00354 {
00355 c = ClassCache.find(*ci);
00356 if (c == end)
00357 {
00358 c = Classes.find(*ci);
00359 ClassCache.insert(make_pair(*ci, c->second));
00360 }
00361
00362 assert(c != Classes.end());
00363
00364
00365 output << c->second.getShortInfo() << Endl;
00366 }
00367
00368
00369 output << "// end_message" << Endl;
00370 output << ends;
00371
00372
00373 set<ThreadID>::reverse_iterator susIter;
00374 const set<ThreadID>::reverse_iterator stre = SuspendedThreads.rend();
00375 for (susIter = SuspendedThreads.rbegin(); susIter != stre; ++susIter)
00376 {
00377 CALL(ResumeThread(*susIter));
00378 unsafe_debug("Resumed", *susIter);
00379 }
00380
00381
00382 CALL(EnableGC());
00383 Unlock(output_lock);
00384 Unlock(methods_lock);
00385 Unlock(threads_lock);
00386
00387 Lock(output_lock);
00388 const int chunk = 1024;
00389 const string s = output.str();
00390 const char* cp = s.c_str();
00391
00392
00393 RecordPacket(info.size() + s.size());
00394
00395 Send(info);
00396
00397 for (string::size_type p = 0; p < (s.size()/chunk); p++)
00398 {
00399 Send(cp, chunk);
00400 cp += chunk;
00401 }
00402 Send(cp, strlen(cp));
00403 Unlock(output_lock);
00404
00405 LeaveRelease;
00406 unsafe_debug("perf ", "");
00407 unsafe_debug("perf classes to send count", classes_to_send.size());
00408 unsafe_debug("perf Classes", Classes.size());
00409 unsafe_debug("perf ClassesCache", ClassCache.size());
00410 unsafe_debug("perf methods to send count", methods_to_send.size());
00411 unsafe_debug("perf MethodsCache = ", MethodCache.size());
00412 unsafe_debug("perf Methods = ", Methods.size());
00413
00414
00415
00416 ofstream outtrace("network.txt");
00417 outtrace << info << s << endl;
00418
00419 debug("message", s.size());
00420 debug(s);
00421
00422 }
00423
00424