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(¶ms);
......
}
启动端口监听
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))
......
}