Android主线程的名称“main“是在哪里设置进去的?

目录

  • 为什么问这个问题?
  • ZygoteInit.main方法,又是在哪里被执行的?
  • `AndroidRuntime.start`函数有设置线程名称为"main"吗?
  • 先创建线程,还是先执行ZygoteInit.main()?
  • 代码实测下主线程的名称是不是“main”

为什么问这个问题?

常说:handler把子线程的消息发送给主线程,这个主线程具体是在哪里创建的?这个问题比较复杂。上篇文章:ActivityThread的main方法在哪里被调用的? 我们得出结论:ActivityThread的main方法是被ZygoteInit.main()方法调用的。这篇文章接着分析主线程的名称"main"是在哪里设置进去的?

ZygoteInit.main方法,又是在哪里被执行的?

答:AndroidRuntime.start函数里面。在目录/frameworks/base/core/jni/AndroidRuntime.cpp中可以看到start函数完整源码,结合Android系统启动-zygote篇就能知道具体流程。

AndroidRuntime.start函数有设置线程名称为"main"吗?

答:有,Zygote启动虚拟机的时候。

AndroidRuntime.start函数中,有调用startVM

/frameworks/base/core/jni/AndroidRuntime.cpp

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool primary_zygote)
{
   JavaVMInitArgs initArgs;
    // 前面一大片代码都是都是用来设置ART虚拟机的启动参数的,这里先略过
    ......

    initArgs.version = JNI_VERSION_1_4;
    initArgs.options = mOptions.editArray();
    initArgs.nOptions = mOptions.size();
    initArgs.ignoreUnrecognized = JNI_FALSE;
	
	//重点在这里
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failed\n");
        return -1;
    }

    return 0;
}

上面代码中最后调用JNI_CreateJavaVM来创建虚拟机,这里的JNI_CreateJavaVM是在/libnativehelper/JniInvocation.cpp中进行实现的。这里要介绍一个库libart.so,JNI_CreateJavaVMlibart.so的关系参考:基于Android R之ART虚拟机的创建流程。libart.so库中的JNI_CreateJavaVM是在java_vm_ext.cc这个文件中实现的。

/art/runtime/java_vm_ext.cc

extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
  ScopedTrace trace(__FUNCTION__);
  const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
  // 虚拟机参数准备,省略具体的过程
  // ......

  //调用Runtime::Create方法,这里就是进行Runtime对象的创建的
  if (!Runtime::Create(options, ignore_unrecognized)) {
    return JNI_ERR;
  }

  // 初始化并加载其他系统动态库,需要加载的动态库都定义在/etc/public.libraryies.txt文件中
  android::InitializeNativeLoader();

  //获取当前runtime对象并调用Start进行启动
  Runtime* runtime = Runtime::Current();
  //***********在这里调用runtime.cc文件中的Start()函数
  //***********后面详细贴出源代码
  bool started = runtime->Start();
  if (!started) {
    delete Thread::Current()->GetJniEnv();
    delete runtime->GetJavaVM();
    LOG(WARNING) << "CreateJavaVM failed";
    return JNI_ERR;
  }

  // 保存当前线程和进程的JinEnv和JavaVM对象,JinEnv是每个线程一个,不同线程之间的JinEnv是不同的
  //JavaVM是一个进程只有一个
  *p_env = Thread::Current()->GetJniEnv();
  *p_vm = runtime->GetJavaVM();
  return JNI_OK;
}


Runtime.Start函数中,调用了 Thread::FinishStartup();

/art/runtime/runtime.cc

bool Runtime::Start() {
  ......
  //这里调用了FinishStartup函数
  Thread::FinishStartup();
  ......
  return true;
}

从上面的代码,可以看到Start()函数调用了FinishStartup

/art/runtime/thread.cc

void Thread::FinishStartup() {
  Runtime* runtime = Runtime::Current();
  CHECK(runtime->IsStarted());

  // Finish attaching the main thread.
  ScopedObjectAccess soa(Thread::Current());
  //将线程名称设为“main”
  soa.Self()->CreatePeer("main", false, runtime->GetMainThreadGroup());
  ...
}

//CreatePeer函数内部会调用SetThreadName再次修改线程的名称。
void Thread::CreatePeer(const char* name, bool as_daemon, jobject thread_group) {
	...
  MutableHandle<mirror::String> peer_thread_name(hs.NewHandle(GetThreadName(soa)));
	...
  if (peer_thread_name.Get() != nullptr) {
    SetThreadName(peer_thread_name->ToModifiedUtf8().c_str());
  }
}

//SetThreadName函数
void Thread::SetThreadName(const char* name) {
  tlsPtr_.name->assign(name);
  ::art::SetThreadName(name);
  Dbg::DdmSendThreadNotification(this, CHUNK_TYPE("THNM"));
}

当虚拟机启动完毕后,zygote的主线程名更改为"main"。
Android中的进程名和线程名
基于Android R之ART虚拟机的创建流程

先创建线程,还是先执行ZygoteInit.main()?

先创建线程,然后执行ZygoteInit.main函数。通过AndroidRuntime.start函数源码可以看出,先调用startVm,startReg,然后通过反射调用了ZygoteInit.main函数。

代码实测下主线程的名称是不是“main”

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i(TAG, "onCreate: 当前线程名称:" + Thread.currentThread().getName());
        Thread.currentThread().setName("yyy");
        Log.i(TAG, "onCreate: 修改后线程名称:" + Thread.currentThread().getName());
    }
}

输出:

I/MainActivity: onCreate: 当前线程名称:main
I/MainActivity: onCreate: 修改后线程名称:yyy

可以看出:MainActivity的onCreate方法确实在main线程中执行,这个线程名称也可以修改。

你可能感兴趣的:(Handler,android)