Android jdwp 原理

Android jdwp 原理

jdwp 工做原理

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

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

JNI_CreateJavaVM 建立虚拟机

实际是使用dvmStartup 去建立核心类,基础线程等工做。web

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是实际调用的地方。less

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)) 
...... 
相关文章
相关标签/搜索