jdwp(java debug wire protocol)是dalvik VM的一个线程,可以建立在adb或者tcp基础上,与DDMS或debugger进行通信。
代码位置
dalvik/vm/jdwp
frameworks/base/core/jni
java虚拟机初始化后,或者每次“zygote fork”出一个新进程时,会启动jdwp线程。关于虚拟机的初始化参考我的博客http://blog.csdn.net/yinlijun2004/article/details/6065979。
主要调用路径:dvmStartup->dvmInitAfterZygote->dvmInitJDWP
dvmInitJDWP线程启动之前会可能会阻塞VM,依赖于配置suspend=n,所以dvmInitJDWP放在dvmStartup的最后步骤来执行。/* enable debugging; set suspend=y to pause during VM init */ #ifdef HAVE_ANDROID_OS /* use android ADB transport */ opt.optionString = "-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y"; #else /* use TCP socket; address=0 means start at port 8000 and probe up */ LOGI("Using TCP socket for JDWP\n"); opt.optionString = "-agentlib:jdwp=transport=dt_socket,suspend=n,server=y,address=0"; #endif
if (gDvm.jdwpAllowed && gDvm.jdwpConfigured) { JdwpStartupParams params; if (gDvm.jdwpHost != NULL) { if (strlen(gDvm.jdwpHost) >= sizeof(params.host)-1) { LOGE("ERROR: hostname too long: '%s'\n", gDvm.jdwpHost); return false; } strcpy(params.host, gDvm.jdwpHost); } else { params.host[0] = '\0'; } params.transport = gDvm.jdwpTransport; params.server = gDvm.jdwpServer; params.suspend = gDvm.jdwpSuspend; params.port = gDvm.jdwpPort; gDvm.jdwpState = dvmJdwpStartup(¶ms); if (gDvm.jdwpState == NULL) { LOGW("WARNING: debugger thread failed to initialize\n"); /* TODO: ignore? fail? need to mimic "expected" behavior */ } }
switch (pParams->transport) { case kJdwpTransportSocket: // LOGD("prepping for JDWP over TCP\n"); state->transport = dvmJdwpSocketTransport(); break; case kJdwpTransportAndroidAdb: // LOGD("prepping for JDWP over ADB\n"); state->transport = dvmJdwpAndroidAdbTransport(); /* TODO */ break; default: LOGE("Unknown transport %d\n", pParams->transport); assert(false); goto fail; }
typedef struct JdwpTransport { bool (*startup)(struct JdwpState* state, const JdwpStartupParams* pParams); bool (*accept)(struct JdwpState* state); bool (*establish)(struct JdwpState* state); void (*close)(struct JdwpState* state); void (*shutdown)(struct JdwpState* state); void (*free)(struct JdwpState* state); bool (*isConnected)(struct JdwpState* state); bool (*awaitingHandshake)(struct JdwpState* state); bool (*processIncoming)(struct JdwpState* state); bool (*sendRequest)(struct JdwpState* state, ExpandBuf* pReq); bool (*sendBufferedRequest)(struct JdwpState* state, const struct iovec* iov, int iovcnt); } JdwpTransport;
#define kJdwpControlName "\0jdwp-control"
int ret = connect(netState->controlSock, &netState->controlAddr.controlAddrPlain, netState->controlAddrLen);
snprintf(buff, sizeof(buff), "%04x", getpid()); buff[4] = 0; do { ret = send( netState->controlSock, buff, 4, 0 ); } while (ret < 0 && errno == EINTR);
netState->clientSock = receiveClientFd(netState);
while (true) { // sanity check -- shouldn't happen? if (dvmThreadSelf()->status != THREAD_VMWAIT) { LOGE("JDWP thread no longer in VMWAIT (now %d); resetting\n", dvmThreadSelf()->status); dvmDbgThreadWaiting(); } if (!dvmJdwpProcessIncoming(state)) /* blocking read */ break; if (first && !dvmJdwpAwaitingHandshake(state)) { /* handshake worked, tell the interpreter that we're active */ first = false; /* set thread ID; requires object registry to be active */ state->debugThreadId = dvmDbgGetThreadSelfId(); /* wake anybody who's waiting for us */ dvmDbgLockMutex(&state->attachLock); dvmDbgCondBroadcast(&state->attachCond); dvmDbgUnlockMutex(&state->attachLock); } }
typedef struct { u1 cmdSet; u1 cmd; JdwpRequestHandler func; const char* descr; } JdwpHandlerMap;