zoukankan      html  css  js  c++  java
  • Android jdwp 原理

    Android jdwp 原理

    jdwp 工作原理

    • 在setCommandLineDefaults 里面设置了开关,默认开启。

    • 在dvmJdwpStartup 里面会设置sock或者adb 方式打开监听

    JNI_CreateJavaVM 创建虚拟机

    实际是使用dvmStartup 去创建核心类,基础线程等工作。

    JNIEnvExt* pEnv = (JNIEnvExt*) dvmCreateJNIEnv(NULL); 
     
    /* Initialize VM. */ 
    gDvm.initializing = true
    std::string status = 
    dvmStartup(argc, argv.get(), args->ignoreUnrecognized, (JNIEnv*)pEnv); 
    gDvm.initializing = false

    调用setCommandLineDefault,设置默认启动参数

    std::string dvmStartup(int argc, const char* const argv[], 
    bool ignoreUnrecognized, JNIEnv* pEnv) 

    ScopedShutdown scopedShutdown; 
    assert(gDvm.initializing); 
    LOGV("VM init args (%d):", argc); 
    for (int i = 0; i < argc; i++) { 
    LOGV(" %d: '%s'", i, argv[i]); 

    //这里会设置一些默认参数。 
    setCommandLineDefaults(); 
    ...... 
    if (gDvm.zygote) { 
    if (!initZygote()) { 
    return "initZygote failed"

    } else
    if (!dvmInitAfterZygote()) { 
    return "dvmInitAfterZygote failed"


    ...... 

    需要注意的是CLASSPATH路径填充,和jdwp启动开关

    static void setCommandLineDefaults() 

    const char* envStr = getenv("CLASSPATH"); 
    if (envStr != NULL) { 
    gDvm.classPathStr = strdup(envStr); 
    } else
    gDvm.classPathStr = strdup("."); 

    envStr = getenv("BOOTCLASSPATH"); 
    if (envStr != NULL) { 
    gDvm.bootClassPathStr = strdup(envStr); 
    } else
    gDvm.bootClassPathStr = strdup("."); 

    ...... 
    gDvm.concurrentMarkSweep = true
    /* gDvm.jdwpSuspend = true; */ 
    //这里设置是否开启jdwp 
    /* allowed unless zygote config doesn't allow it */ 
    gDvm.jdwpAllowed = true

    具体的配置参数,由启动参数传进

    static void showJdwpHelp() 

    dvmFprintf(stderr, 
    "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y "); 
    dvmFprintf(stderr, 
    "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n "); 

    static bool handleJdwpOption(const char* name, const char* value) 

    if (strcmp(name, "transport") == 0) { 
    //这里决定使用adb方式,还是socket方式。 
    if (strcmp(value, "dt_socket") == 0) { 
    gDvm.jdwpTransport = kJdwpTransportSocket; 
    } else if (strcmp(value, "dt_android_adb") == 0) { 
    gDvm.jdwpTransport = kJdwpTransportAndroidAdb; 
    } else
    LOGE("JDWP transport '%s' not supported", value); 
    return false

    //是否启动服务 
    } else if (strcmp(name, "server") == 0) { 
    if (*value == 'n'
    gDvm.jdwpServer = false
    else if (*value == 'y'
    gDvm.jdwpServer = true
    else
    LOGE("JDWP option 'server' must be 'y' or 'n'"); 
    return false

    //启动后是否挂起 
    } else if (strcmp(name, "suspend") == 0) { 
    if (*value == 'n'
    gDvm.jdwpSuspend = false
    else if (*value == 'y'
    gDvm.jdwpSuspend = true
    else
    LOGE("JDWP option 'suspend' must be 'y' or 'n'"); 
    return false

    //绑定地址 
    } else if (strcmp(name, "address") == 0) { 
    ...... 

    dvmInitAfterZygote 里面会调用initJdwp去初始化jdwp。

    static bool initJdwp() 

    assert(!gDvm.zygote); 
    /× 
    * 这里设置是否开启jdwp 服务。 
    */ 
    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'", gDvm.jdwpHost); 
    return false

    strcpy(params.host, gDvm.jdwpHost); 
    } else
    params.host[0] = ''

    params.transport = gDvm.jdwpTransport; 
    params.server = gDvm.jdwpServer; 
    params.suspend = gDvm.jdwpSuspend; 
    params.port = gDvm.jdwpPort; 
     
    gDvm.jdwpState = dvmJdwpStartup(&params); 
    ...... 

    启动端口监听

    adb会使用dvmJdwpAndroidAdbTransport绑定jdwp调用接口,socket会使用dvmJdwpSocketTransport,dvmJdwpNetStartup是实际调用的地方。

    JdwpState* dvmJdwpStartup(const JdwpStartupParams* pParams) 

    JdwpState* state = NULL; 
    /* comment this out when debugging JDWP itself */ 
    android_setMinPriority(LOG_TAG, ANDROID_LOG_DEBUG); 
    state = (JdwpState*) calloc(1, sizeof(JdwpState)); 
    ...... 
    switch (pParams->transport) { 
    case kJdwpTransportSocket: 
    // LOGD("prepping for JDWP over TCP"); 
    state->transport = dvmJdwpSocketTransport(); 
    break
    case kJdwpTransportAndroidAdb: 
    // LOGD("prepping for JDWP over ADB"); 
    state->transport = dvmJdwpAndroidAdbTransport(); 
    /* TODO */ 
    break
    default
    LOGE("Unknown transport %d", pParams->transport); 
    assert(false); 
    goto fail; 

     
    if (!dvmJdwpNetStartup(state, pParams)) 
    ...... 

  • 相关阅读:
    3、面向对象
    今日记事
    javascript 学习javascript高级程序设计
    数据库操作语言分类
    project遇到问题了。
    CentOS设置程序开机自启动的方法
    ECMAScript 基础 [完]
    CentOS 网络设置修改
    Spring Boot项目Circular view path问题解决
    数据库设计
  • 原文地址:https://www.cnblogs.com/rexonor/p/4940587.html
Copyright © 2011-2022 走看看