【问题标题】:How main thread created by JavaJava如何创建主线程
【发布时间】:2013-07-02 18:19:55
【问题描述】:

我是 Java 技术的新手。我知道在Java中创建Thread只有两种方法

  • 扩展线程类
  • 实现可运行接口

所以这只是创建Thread 的两种方式。但是当我们用主 JVM 启动我们的程序时,启动了一个主 Thread。我认为即使是 JVM 也必须遵循创建主线程的规则 Thread 意味着创建主线程 JVM 要么必须扩展 Thread 类,要么实现 Runnable

public class MainThreadExample {

    public static void main(String[] args) {

        Thread t=Thread.currentThread();            
        System.out.println(t.getName());            
    }
}

我尽力了,但不知道 JVM 是如何创建这个主对象的。当我完全通过主类(sun.tool.jar)时,我知道这是负责主线程的类。但是在谷歌中搜索了这么多网页后无法得到它。所以请帮忙,如果可能的话,也请参考我的例子或链接。

P.S:我正在学习 Java 技术,我不应该为他们创建 main 的方式而烦恼,而这一切都是设计的事情。但我认为这是一个合乎逻辑的问题

【问题讨论】:

  • 我猜这是Thread的匿名子类
  • t.getClass().getFullName() 说什么?
  • 没有任何规则,如果我们没有看到 Runnable 和 Thread 家伙所以没有任何线程,一个方法会被一个线程触发,你也可以通过反射运行每个线程,而他们不是 void run(),JVM 创建一个线程并在线程内部调用 main 方法
  • 我认为 Java 运行时本身不必遵循 Java 规则来创建线程,因为它不是在 Java 中实现的。我怀疑垃圾收集器也在它自己的线程中运行,并且(据我所知)GC 做了一些 Java 做不到的事情。
  • 与答案无关,我找到了这篇关于java线程的详细文章。我想你会喜欢阅读。 blog.jamesdbloom.com/JVMInternals.html

标签: java


【解决方案1】:

java.lang.Thread 的实例不是线程;它可以用来表示 JVM 中的一个执行线程,但 JVM 完全能够在不使用 Thread 类的情况下创建线程。

这就是主线程发生的事情:JVM 创建它,然后创建一个 java.lang.Thread 的实例来表示它。

在 Hotspot JVM 中,在 src/share/vm/runtime/thread.hppsrc/share/vm/runtime/thread.cpp 中定义的 Threads 类中有很多与线程相关的代码。 JVM的启动调用了静态Threads::create_vm函数,该函数已经在操作系统设置的线程中运行。在该函数中,我们发现:

(src/share/vm/runtime/thread.cpp)
3191   // Attach the main thread to this os thread
3192   JavaThread* main_thread = new JavaThread();
3193   main_thread->set_thread_state(_thread_in_vm);
3194   // must do this before set_active_handles and initialize_thread_local_storage
3195   // Note: on solaris initialize_thread_local_storage() will (indirectly)
3196   // change the stack size recorded here to one based on the java thread
3197   // stacksize. This adjusted size is what is used to figure the placement
3198   // of the guard pages.
3199   main_thread->record_stack_base_and_size();
3200   main_thread->initialize_thread_local_storage();

JavaThread 类显然是用来记账的;它将 OS 或 VM 线程与 Java Thread 对象相关联。 Java 对象显然还不存在。然后代码继续初始化各种其他的东西,后来仍然在同一个函数中我们发现:

3335     // Initialize java_lang.System (needed before creating the thread)
3336     if (InitializeJavaLangSystem) {
3337       initialize_class(vmSymbols::java_lang_System(), CHECK_0);
3338       initialize_class(vmSymbols::java_lang_ThreadGroup(), CHECK_0);
3339       Handle thread_group = create_initial_thread_group(CHECK_0);
3340       Universe::set_main_thread_group(thread_group());
3341       initialize_class(vmSymbols::java_lang_Thread(), CHECK_0);
3342       oop thread_object = create_initial_thread(thread_group, main_thread, CHECK_0);
3343       main_thread->set_threadObj(thread_object);
3344       // Set thread status to running since main thread has
3345       // been started and running.
3346       java_lang_Thread::set_thread_status(thread_object,
3347                                           java_lang_Thread::RUNNABLE);

换句话说,我们初始化SystemThreadGroupThread类,然后创建Thread的实例,由thread_object引用(第3342行),并设置Thread实例为主要的JavaThread

如果你想知道create_initial_thread 做了什么,显然它分配了 Thread 实例,将指向 JavaThread (C++) 对象的指针存储在 Thread 实例的私有 eetop 字段中,将线程优先级字段设置为正常,调用Thread(ThreadGroup group,String name)构造函数,并返回实例:

 967 // Creates the initial Thread
 968 static oop create_initial_thread(Handle thread_group, JavaThread* thread, TRAPS) {
 969   klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_     NULL);
 970   instanceKlassHandle klass (THREAD, k);
 971   instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL);
 972 
 973   java_lang_Thread::set_thread(thread_oop(), thread);
 974   java_lang_Thread::set_priority(thread_oop(), NormPriority);
 975   thread->set_threadObj(thread_oop());
 976 
 977   Handle string = java_lang_String::create_from_str("main", CHECK_NULL);
 978 
 979   JavaValue result(T_VOID);
 980   JavaCalls::call_special(&result, thread_oop,
 981                                    klass,
 982                                    vmSymbols::object_initializer_name(),
 983                                    vmSymbols::threadgroup_string_void_signature(),
 984                                    thread_group,
 985                                    string,
 986                                    CHECK_NULL);
 987   return thread_oop();
 988 }

现在,这就是 Hotspot VM 的作用。其他实现,如 IBM J9、Oracle JRockit 或 Azul Zing 可能会做类似的事情。

【讨论】:

  • 非常感谢您回答 Joni。但是您能否详细说明 Java 是如何制作 Java.lang.Thread 实例来表示它的。我浏览了整个 main 和 Thread 类但没有它
  • 主线程和代表它的java.lang.Thread 对象必须在本机代码中创建。我会看看 OpenJDK 的源代码,也许我可以确定位置。
  • 这将是很大的帮助..非常感谢您的帮助
  • 看更新,有不清楚的地方问一下,Java和C++对象像这样一起使用和混合的时候解释起来很复杂。
【解决方案2】:

我相信确切的机制是特定于 JVM 的。规格有点模糊,但Thread Javadoc 提供以下功能:

当 Java 虚拟机启动时,通常有一个非守护线程(通常调用某个指定类的名为 main 的方法)。

它如何映射到 Thread 类的实例似乎没有指定。

【讨论】:

  • 当您说“规范有点模糊”时,您指的是 JLS/JVMS 的哪一部分?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-28
  • 2021-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-08
相关资源
最近更新 更多