【发布时间】:2022-10-06 10:16:01
【问题描述】:
在我开始一个 SpringBoot web 项目之后。我找不到使用jcmd $pid Thread.print 的主线程。我也找不到使用hsdb 的主线程。 main 线程去哪儿了?
在我开始一个 SpringBoot web 项目之后。我找不到使用jcmd $pid Thread.print 的主线程。我也找不到使用hsdb 的主线程。 main 线程去哪儿了?
我不知道您用于创建 Spring Boot 项目的工具,但如果您通过 Spring Initializr (https://start.spring.io/) 创建它,它应该在路径 YOUR_PROJECT_NAME/src/main/java/YOUR_PERSONALIZED_PATH/ 上。
创建/执行main thread 的文件的名称应该在该路径内,并且应该称为YOUR_PROJECT_NAME+Application.java。
【讨论】:
对于大多数 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);
}
}
【讨论】:
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() 按预期工作。
在这种情况下,进程具有非守护线程,因此进程不会退出。
【讨论】: