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的最后步骤来执行。
dvmInitJDWP首先判断jdwp是否允许并且已经配置好,如果是,则读取jdwp的配置,这些配置是AndroidRuntime::startVm中配置的,

[cpp] view plaincopy
  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交换数据,

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

其中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

[cpp] view plaincopy
  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。

[cpp] view plaincopy
  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名称

[cpp] view plaincopy
  1. #define kJdwpControlName    "\0jdwp-control"

这个socket名称已经被adbd绑定。
然后,调用dvmCreateInternalThread启动jdwp线程,dvmCreateInternalThread是pthread_create的包装,最终线程的执行函数是jdwpThreadStart,
在jdwpThreadStart中,会调用dvmJdwpEstablishConnection与adbd建立连接。在dvmJdwpEstablishConnection中,会一直等待与adbd的连接,直到连接成功

[cpp] view plaincopy
  1. int  ret = connect(netState->controlSock,
  2. &netState->controlAddr.controlAddrPlain,
  3. netState->controlAddrLen);

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

[cpp] view plaincopy
  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返回一个客户文件描述符,

[cpp] view plaincopy
  1. netState->clientSock = receiveClientFd(netState);

如果返回成功,这个clientSock将用来直接与debugger或DDMS通信。可以想象,这里的clientSock就是TCP:5037对应的client描述符。
这样acceptConnection也成功返回了,回到jdwp线程处理函数jdwpThreadStart,接着进入一个while循环从adbd读取并处理握手消息。

[cpp] view plaincopy
  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. if (!dvmJdwpProcessIncoming(state))     /* blocking read */
  9. break;
  10. if (first && !dvmJdwpAwaitingHandshake(state)) {
  11. /* handshake worked, tell the interpreter that we're active */
  12. first = false;
  13. /* set thread ID; requires object registry to be active */
  14. state->debugThreadId = dvmDbgGetThreadSelfId();
  15. /* wake anybody who's waiting for us */
  16. dvmDbgLockMutex(&state->attachLock);
  17. dvmDbgCondBroadcast(&state->attachCond);
  18. dvmDbgUnlockMutex(&state->attachLock);
  19. }
  20. }

先看dvmJdwpProcessIncoming函数,在里面执行select,可能会收到三种数据,对应三个文件描述被set,其中wakeFds是定时唤醒作用,丢弃,controlSock的set也忽略,因为不需要接收第二个debugger文件描述服。之后收到debugger的数据,也就是clientSock被set的时候调用read读取数据,如果不一个单位数据包长度,则dvmJdwpProcessIncoming返回。否则,调用handlePacket处理数据包,
handlePacket->dvmJdwpProcessRequest->write
handlePacket从讲包中的数据还原成JdwpReqHeader和数据起始指针,送给dvmJdwpProcessRequest处理,dvmJdwpProcessRequest从gHandlerMap调出处理函数func

[cpp] view plaincopy
  1. typedef struct {
  2. u1  cmdSet;
  3. u1  cmd;
  4. JdwpRequestHandler  func;
  5. const char* descr;
  6. } JdwpHandlerMap;

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

Android开发工具——ADB(Android Debug Bridge) 三DalvikVM之jdwp线程相关推荐

  1. Android开发工具——ADB(Android Debug Bridge) 一概览

    Android Debug Bridge (adb) 是一个android开发人员必会的多功能的调试工具,确实它的名字一样,它在开发者和目标机器之间,架起了一座bridge. adb的用法很简单,只要 ...

  2. Android开发工具——ADB(Android Debug Bridge) 二HOST端

    我分析代码的喜欢从main函数开始,因为还不知道代码结构的情况下,这是最直接的方法.所以先看adb.c的main函数 [cpp] view plaincopy int main(int argc, c ...

  3. 全网最全Android开发工具,Android开发框架大全

    涵盖Android方方面面的技术, 目前保持更新. 时刻与Android开发流行前沿同步. 目录 一.工具 Android开发工具 在线工具宝典大全 二.框架 *缓存框架* DiskLruCache ...

  4. Android开发工具视频Android 12(S)准备

    Android开发工具视频Android 12(S)准备 适配步骤 下载最新的Android studio工具,点我到官网下载最新的吧! 最新版的studio规定jdk使用必须至少11,所以请移步下载 ...

  5. Android 开发工具集合 - (Android Dev Tools)

    收集整理Android开发所需的Android SDK.开发中用到的工具.Android开发教程.Android设计规范,免费的设计素材等. 欢迎大家推荐自己在Android开发过程中用的好用的工具. ...

  6. Eclipse调试Android开发工具ADB

    要使用adb就要先配置adb的环境变量 http://jingyan.baidu.com/article/17bd8e52f514d985ab2bb800.html 配置完了之后,就可以使用adb的命 ...

  7. 盘点android 开发工具,盘点Android开发者必备的十大开发工具

    Android SDK提供了一系列可帮助开发者设计.创建.测试和发布Android应用程序的强大工具,以下是游戏邦编译developer推荐的10款最常用的开发工具. 1.Eclipse w/ADT ...

  8. Android开发工具之Android Studio----Gradle

    .gradle 文件介绍 一个 Android Studio 项目中,会存在多个 .gradle 文件.其中, project 目录下存在一个 build.gradle 文件和一个 settings. ...

  9. Android开发工具之Android Studio---版本控制SVN使用三(常规操作)

    1.提交 点击 提交本地变动.提交的操作与上面初始提交一样. 错误:如果本地version低于服务器,直接提交则会报错.此时需要先更新,再提交. 2.更新 点击标题栏 更新整个project,或者某个 ...

最新文章

  1. 6分钟完成ImageNet训练,NVIDIA创下六项AI性能新记录!
  2. Java字符串格式化
  3. python好不好用_但python以前不太好用
  4. git放弃本地文件修改
  5. 021:自定义path(或url)转换器
  6. 25--最后一个单词的长度
  7. 求$N^N$的首位数字
  8. Node.js 指南(入门指南)
  9. collections模块 :namedtuple、deque、defaultdict、OrderedDict、ChainMap、Counter
  10. try-catch(C# 参考)
  11. 这5款功能强大、堪称最良心的浏览器,简直好用极了!
  12. Virtual Display Manager(windows虚拟显示器软件)官方中文版V3.3.2.44650 | Win7/win10虚拟显示器下载
  13. unity3d贪吃蛇游戏源码,支持安卓+IOS双端 unity2019 C#语言开发
  14. HDU6184 Counting Stars(三元环计数)
  15. 不均衡分类问题 之 class weight sample weight
  16. 中国大学MOOC所有课程信息爬虫(课程ID、学校简称、课程名字、教师、学校全称、学生人数、学生人数、评价人数、平均评价)
  17. 今天看到一篇文章,收藏了很多大牛的博客
  18. iPhone OS 4.0发布 苹果手机进入多任务时代
  19. NYOJ - 找点【贪心】
  20. 极客日报:iPhone 13或有8款配色;vivo百万年薪招工程师;特斯拉新增行车记录视频紧急情况自动保存功能

热门文章

  1. 前端各种类型文件的转换
  2. Windows XP SP3远程桌面连接支持网络级身份验证配置
  3. HeadFirst 设计模式 - Chapte5 单例模式
  4. 深入理解java类加载
  5. RIM 将在今天发布新的 BlackBerry 7 OS 手机
  6. nodejs web开发入门: Simple-TODO Nodejs 实现版
  7. 函数的实参 函数的形参 闭包 js
  8. REST POST PUT差别
  9. android 强制设置横屏 判断是横屏还是竖屏
  10. Lucene教程具体解释