【问题标题】:There is no main thread in the SpringBoot web projectSpring Boot web项目中没有主线程
【发布时间】:2022-10-06 10:16:01
【问题描述】:

在我开始一个 SpringBoot web 项目之后。我找不到使用jcmd $pid Thread.print 的主线程。我也找不到使用hsdb 的主线程。 main 线程去哪儿了?

    标签: spring-boot spring-mvc


    【解决方案1】:

    我不知道您用于创建 Spring Boot 项目的工具,但如果您通过 Spring Initializr (https://start.spring.io/) 创建它,它应该在路径 YOUR_PROJECT_NAME/src/main/java/YOUR_PERSONALIZED_PATH/ 上。

    创建/执行main thread 的文件的名称应该在该路径内,并且应该称为YOUR_PROJECT_NAME+Application.java

    【讨论】:

      【解决方案2】:

      对于大多数 Spring Boot 应用程序,SpringApplication::run 涉及启动 Web 服务器(Tomcat、Undertow、Jetty、Netty)。这些服务器创建自己的非守护线程。对SpringApplication::run 的调用然后返回并且主线程退出。然后,VM 由其他非守护线程保持活动状态——确切的名称取决于所使用的 Web 服务器。

      @SpringBootApplication
      public class App {
          public static void main(String[] args) {
              SpringApplication.run(App.class, args);
          }
      }
      

      【讨论】:

        【解决方案3】:

        Web应用程序将main方法委托给SpringApplication.run,它将执行Spring初始化等过程。 Spring初始化完成后,main方法的生命周期就结束了。

        为什么没有main方法java进程不退出?
        java.c

        /* Build platform specific argument array */
        mainArgs = CreateApplicationArgs(env, argv, argc);
        CHECK_EXCEPTION_NULL_LEAVE(mainArgs);
        
        /* Invoke main method. */
        (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
        
        /*
         * The launcher's exit code (in the absence of calls to
         * System.exit) will be non-zero if main threw an exception.
         */
        ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
        LEAVE();
        
        #define LEAVE() \
        do { \
            if ((*vm)->DetachCurrentThread(vm) != JNI_OK) { \
                JLI_ReportErrorMessage(JVM_ERROR2); \
                ret = 1; \
            } \
            if (JNI_TRUE) { \
                (*vm)->DestroyJavaVM(vm); \
                return ret; \
            } \
        } while (JNI_FALSE)
        

        因为在休假宏定义的cmets中有说明。

        始终分离主线程,以便在应用程序的 main 方法退出时它似乎已经结束。如果 main 抛出异常,这将调用未捕获的异常处理程序机制。未捕获的异常处理程序不能更改启动器的返回码,除非调用 System.exit。 等待所有非守护线程结束,然后销毁 VM。这实际上将创建一个名为“DestroyJavaVM”的简单的新 Java 服务程序线程,但这将被视为与执行 main 的线程不同的线程,即使它们是同一个 C 线程。这允许 mainThread.join() 和 mainThread.isAlive() 按预期工作。

        在这种情况下,进程具有非守护线程,因此进程不会退出。

        【讨论】:

          猜你喜欢
          • 2018-10-18
          • 1970-01-01
          • 2018-11-30
          • 1970-01-01
          • 2021-03-02
          • 2016-05-22
          • 1970-01-01
          • 2019-07-13
          • 2018-02-03
          相关资源
          最近更新 更多