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\n"); 
dvmFprintf(stderr, 
"Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n\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] = '\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)) 
...... 

posted @ 2015-11-05 19:43  rexonor  阅读(1336)  评论(0编辑  收藏  举报