jdwp(java debug wire protocol)是dalvik VM的一个线程,可以建立在adb或者tcp基础上,与DDMS或debugger进行通信。

       代码位置:

       dalvik/vm/jdwp

       frameworks/base/core/jni


       java虚拟机初始化后,或者每次“zygote fork”出一个新进程时,会启动jdwp线程。

       主要调用路径:dvmStartup->dvmInitAfterZygote->dvmInitJDWP。

       dvmInitJDWP线程启动之前会可能会阻塞VM,依赖于配置suspend=n,所以dvmInitJDWP放在dvmStartup的最后步骤来执行。

       dvmInitJDWP首先判断jdwp是否允许并且已经配置好,如果是,则读取jdwp的配置,这些配置是AndroidRuntime::startVm中配置的。

C++代码
  1.     /* enable debugging; set suspend=y to pause during VM init */  
  2. #ifdef HAVE_ANDROID_OS   
  3.     /* use android ADB transport */  
  4.     opt.optionString =   
  5.         "-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y";   
  6. #else   
  7.     /* use TCP socket; address=0 means start at port 8000 and probe up */  
  8.     LOGI("Using TCP socket for JDWP\n");   
  9.     opt.optionString =   
  10.         "-agentlib:jdwp=transport=dt_socket,suspend=n,server=y,address=0";   
  11. #endif  

       这些配置保存在虚拟机全局变量gDvm中,gDvm是DvmGlobals变量,需要读取的配置包括transport,负责与ADB或TCP交换数据。

C++代码
  1. if (gDvm.jdwpAllowed && gDvm.jdwpConfigured) {   
  2.     JdwpStartupParams params;   
  3.   
  4.   
  5.     if (gDvm.jdwpHost != NULL) {   
  6.         if (strlen(gDvm.jdwpHost) >= sizeof(params.host)-1) {   
  7.             LOGE("ERROR: hostname too long: '%s'\n", gDvm.jdwpHost);   
  8.             return false;   
  9.         }   
  10.         strcpy(params.host, gDvm.jdwpHost);   
  11.     } else {   
  12.         params.host[0] = '\0';   
  13.     }   
  14.     params.transport = gDvm.jdwpTransport;   
  15.     params.server = gDvm.jdwpServer;   
  16.     params.suspend = gDvm.jdwpSuspend;   
  17.     params.port = gDvm.jdwpPort;   
  18.   
  19.   
  20.     gDvm.jdwpState = dvmJdwpStartup(¶ms);   
  21.     if (gDvm.jdwpState == NULL) {   
  22.         LOGW("WARNING: debugger thread failed to initialize\n");   
  23.         /* TODO: ignore? fail? need to mimic "expected" behavior */  
  24.     }   
  25. }  

       其中gDvm.jdwpAllowed在dalvik_system_Zygote.c中配置:

       gDvm.jdwpAllowed = ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0);

       gDvm.jdwpConfigured在调用dvmStartup->dvmProcessOptions->parseJdwpOptions时配置。

       参考上面的参数,对照Init.c的handleJdwpOption的函数,可知gDvm.jdwpTransport为kJdwpTransportAndroidAdb,gDvm.jdwpServer为true,gDvm.jdwpSuspend为false,gDvm.jdwpPort没有配置,这些参数保存到dvmJdwpStartup的参数里面。

       再看dvmJdwpStartup,在里面,创建jdwp相关的结构体JdwpState,是先初始化一些互斥锁和条件锁,初始化transport。

C++代码
  1. switch (pParams->transport) {   
  2. case kJdwpTransportSocket:   
  3.     // LOGD("prepping for JDWP over TCP\n");   
  4.     state->transport = dvmJdwpSocketTransport();   
  5.     break;   
  6. case kJdwpTransportAndroidAdb:   
  7.     // LOGD("prepping for JDWP over ADB\n");   
  8.     state->transport = dvmJdwpAndroidAdbTransport();   
  9.     /* TODO */  
  10.     break;   
  11. default:   
  12.     LOGE("Unknown transport %d\n", pParams->transport);   
  13.     assert(false);   
  14.     goto fail;   
  15. }  

       由上文可知,这里执行dvmJdwpAndroidAdbTransport,返回一个JdwpTransport的接口指针结构体,这些在ADB和TCP上各有一套实现方法,对应不同类型的transport。

C++代码
  1. typedef struct JdwpTransport {   
  2.     bool (*startup)(struct JdwpState* state, const JdwpStartupParams* pParams);   
  3.     bool (*accept)(struct JdwpState* state);   
  4.     bool (*establish)(struct JdwpState* state);   
  5.     void (*close)(struct JdwpState* state);   
  6.     void (*shutdown)(struct JdwpState* state);   
  7.     void (*free)(struct JdwpState* state);   
  8.     bool (*isConnected)(struct JdwpState* state);   
  9.     bool (*awaitingHandshake)(struct JdwpState* state);   
  10.     bool (*processIncoming)(struct JdwpState* state);   
  11.     bool (*sendRequest)(struct JdwpState* state, ExpandBuf* pReq);   
  12.     bool (*sendBufferedRequest)(struct JdwpState* state,   
  13.         const struct iovec* iov, int iovcnt);   
  14. } JdwpTransport;  

       然后,调用dvmJdwpNetStartup,在里面实际执行JdwpTransport在ADB上的startup接口。在JdwpADB.c的start函数内,初始化与adb有关的一些网络参数,比如socket名称。

C++代码
  1. #define kJdwpControlName    "\0jdwp-control"    

       这个socket名称已经被adbd绑定。

       然后,调用dvmCreateInternalThread启动jdwp线程,dvmCreateInternalThread是pthread_create的包装,最终线程的执行函数是jdwpThreadStart。

       在jdwpThreadStart中,会调用dvmJdwpEstablishConnection与adbd建立连接。在dvmJdwpEstablishConnection中,会一直等待与adbd的连接,直到连接成功。

C++代码
  1. int  ret = connect(netState->controlSock,                            
  2.                    &netState->controlAddr.controlAddrPlain,          
  3.                    netState->controlAddrLen);             

       如果执行connect成功,则将pid发送给adbd。

C++代码
  1. snprintf(buff, sizeof(buff), "%04x", getpid());   
  2. buff[4] = 0;   
  3.         do {                                                             
  4.             ret = send( netState->controlSock, buff, 4, 0 );             
  5.         } while (ret < 0 && errno == EINTR);       

       接着,jdwp等待adbd返回一个客户文件描述符。

C++代码
  1. netState->clientSock = receiveClientFd(netState);  

       如果返回成功,这个clientSock将用来直接与debugger或DDMS通信。可以想象,这里的clientSock就是TCP:5037对应的client描述符。

       这样acceptConnection也成功返回了,回到jdwp线程处理函数jdwpThreadStart,接着进入一个while循环从adbd读取并处理握手消息。

C++代码
  1. while (true) {   
  2.     // sanity check -- shouldn't happen?   
  3.     if (dvmThreadSelf()->status != THREAD_VMWAIT) {   
  4.         LOGE("JDWP thread no longer in VMWAIT (now %d); resetting\n",   
  5.             dvmThreadSelf()->status);   
  6.         dvmDbgThreadWaiting();   
  7.     }   
  8.   
  9.   
  10.     if (!dvmJdwpProcessIncoming(state))     /* blocking read */  
  11.         break;   
  12.   
  13.   
  14.     if (first && !dvmJdwpAwaitingHandshake(state)) {   
  15.         /* handshake worked, tell the interpreter that we're active */  
  16.         first = false;   
  17.   
  18.   
  19.         /* set thread ID; requires object registry to be active */  
  20.         state->debugThreadId = dvmDbgGetThreadSelfId();   
  21.   
  22.   
  23.         /* wake anybody who's waiting for us */  
  24.         dvmDbgLockMutex(&state->attachLock);   
  25.         dvmDbgCondBroadcast(&state->attachCond);   
  26.         dvmDbgUnlockMutex(&state->attachLock);   
  27.     }   
  28. }  

       先看dvmJdwpProcessIncoming函数,在里面执行select,可能会收到三种数据,对应三个文件描述被set,其中wakeFds是定时唤醒作用,丢弃,controlSock的set也忽略,因为不需要接收第二个debugger文件描述服。

       之后收到debugger的数据,也就是clientSock被set的时候调用read读取数据,如果不是一个单位数据包长度,则dvmJdwpProcessIncoming返回。否则,调用handlePacket处理数据包:handlePacket->dvmJdwpProcessRequest->write。handlePacket将包中的数据还原成JdwpReqHeader和数据起始指针,送给dvmJdwpProcessRequest处理,dvmJdwpProcessRequest从gHandlerMap调出处理函数func。

C++代码
  1. typedef struct {                                                                 
  2.     u1  cmdSet;                                                                  
  3.     u1  cmd;   
  4.     JdwpRequestHandler  func;                                                    
  5.     const char* descr;                                                           
  6. } JdwpHandlerMap;    

       write将结果写回给adbd,adbd处理之后在发回给HOST端。

本文发布:Android开发网
本文地址:http://www.teaching4real.com/android/environment/220.html
2012年9月27日
发布:鸡啄米 分类:Android开发环境 浏览: 注册送白菜网:0