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)) 
...... 
相關文章
相關標籤/搜索