The forked VM terminated without properly saying goodbye. VM crash or System.exit called?

本文最后更新于:2025年2月18日 下午

The forked VM terminated without properly saying goodbye. VM crash or System.exit called?

完整错误:

The forked VM terminated without properly saying goodbye. VM crash or System.exit called? Command was cmd.exe /X /C "D:\Program\Java\jre\bin\java -jar C:\Users\peter\AppData\Local\Temp\surefire8984743116361215564\surefirebooter3828924104254730190.jar C:\Users\peter\AppData\Local\Temp\surefire8984743116361215564 2024-11-17T20-08-43_528-jvmRun1 surefire1713296022132520594tmp surefire_04804249814728176955tmp" Error occurred in starting fork, check output in log Process Exit Code: 1

错误的大致意思是测试进程中遇到System.exit(0);jvm退出代码,导致打包进程中断。

我确实有用到这段代码,但这是项目首次启动初始化数据库信息时发生异常的时候才会执行的逻辑!

去构建输出语句中发现是无法连接数据库:

java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)

原因分析:

我是在开发环境下测试打包没问题后,将配置文件改成生产环境进行打包测试出现的。由于测试环境的数据库在本地是无法访问的,但这不应该是打包无法通过的原因。我一顿搜索,发现是我的测试类中有查询数据库的相关测试。因为在我的数据库初始化逻辑中,当Maven打包时,默认会执行到自定义的测试类中的方法,由于没有指定测试类方法的运行环境,所以在生产环境下打包时,在测试阶段Maven也会尝试连接数据库来测试相关测试类方法,因为连接不到测试类的数据库,从而产生了此问题。

解决方法:

在测试类中指定测试类运行的环境即可。用注解@ActiveProfiles

测试类示例:

1
2
3
4
5
@ActiveProfiles("dev")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerTests {

}

补充:

1. 使用 Maven Surefire 插件配置

Maven 的 Surefire 插件用于运行测试,可以通过配置参数来有条件地运行或跳过特定的测试。

配置 pom.xml

pom.xml 中为 Surefire 插件添加一个 <configuration> 节点,设置跳过特定环境(如生产)的测试:

1
2
3
4
5
6
7
8
9
10
11
12
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M7</version>
<configuration>
<skipTests>${skipTests}</skipTests>
</configuration>
</plugin>
</plugins>
</build>

在打包命令中传递 -DskipTests=true 参数跳过测试:

1
mvn package -DskipTests=true

2. 使用 Spring 的 Profile 控制加载数据库相关测试

通过 Spring 的 @ActiveProfiles@IfProfileValue 注解,可以控制测试方法或测试类是否执行。

示例代码

为测试类指定运行环境(例如,只有在开发环境才执行):

1
2
3
4
5
6
7
8
@ActiveProfiles("dev")
@SpringBootTest
public class DatabaseTests {
@Test
public void testDatabaseConnection() {
// 测试代码
}
}

application.properties 中定义不同环境的配置:

1
2
3
4
5
6
7
8
9
# src/main/resources/application-dev.properties
spring.datasource.url=jdbc:mysql://localhost:3306/devdb
spring.datasource.username=devuser
spring.datasource.password=devpassword

# src/main/resources/application-prod.properties
spring.datasource.url=jdbc:mysql://prod-host:3306/proddb
spring.datasource.username=produser
spring.datasource.password=prodpassword

在生产环境打包时通过命令设置生产环境 Profile:

1
mvn package -Dspring.profiles.active=prod

3. 使用 @EnabledIf@IfProfileValue 注解(仅运行特定环境测试)

你可以基于环境变量有条件地运行测试类。

示例代码
1
2
3
4
5
6
7
@IfProfileValue(name = "env", value = "dev")
public class DatabaseTests {
@Test
public void testDatabaseConnection() {
// 测试代码
}
}

在生产环境打包时传递环境参数跳过测试:

1
mvn package -Denv=prod

4. 通过 Maven 配置排除特定测试

你可以通过 Maven Surefire 插件的 <excludes> 配置跳过特定测试类。

配置 pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M7</version>
<configuration>
<excludes>
<exclude>**/DatabaseTests.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

生产环境打包时这些测试类将不会被执行。


The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
https://superlovelace.top/2024/11/17/生产环境下打包出错/
作者
棱境
发布于
2024年11月17日
更新于
2025年2月18日
许可协议