spring-boot-maven-plugin:run分析

public void execute() throws MojoExecutionException, MojoFailureException {
    if (this.skip) {
        getLog().debug("skipping run as per configuration.");
        return;
    }
    run(getStartClass());
}

private String getStartClass() throws MojoExecutionException {
    String mainClass = this.mainClass;
    if (mainClass == null) {
        try {
            mainClass = MainClassFinder.findSingleMainClass(this.classesDirectory,
                    SPRING_BOOT_APPLICATION_CLASS_NAME);
        }
        catch (IOException ex) {
            throw new MojoExecutionException(ex.getMessage(), ex);
        }
    }
    if (mainClass == null) {
        throw new MojoExecutionException("Unable to find a suitable main class, please add a 'mainClass' property");
    }
    return mainClass;
}

这里涉及到到mainClass的寻找,参考:spring-boot-maven-plugin:repackage分析-优快云博客,我们来看下run方法:

private void run(String startClassName) throws MojoExecutionException, MojoFailureException {
    boolean fork = isFork();
    this.project.getProperties().setProperty("_spring.boot.fork.enabled", Boolean.toString(fork));
    if (fork) {
        doRunWithForkedJvm(startClassName);
    }
    else {
        logDisabledFork();
        runWithMavenJvm(startClassName, resolveApplicationArguments().asArray());
    }
}
protected void logDisabledFork() {
    if (getLog().isWarnEnabled()) {
        if (hasAgent()) {
            getLog().warn("Fork mode disabled, ignoring agent");
        }
        if (hasJvmArgs()) {
            RunArguments runArguments = resolveJvmArguments();
            getLog().warn("Fork mode disabled, ignoring JVM argument(s) ["
                    + String.join(" ", runArguments.asArray()) + "]");
        }
        if (hasWorkingDirectorySet()) {
            getLog().warn("Fork mode disabled, ignoring working directory configuration");
        }
    }
}
先看doRunWithForkedJvm,fork模式启用,允许个性化定制参数
private void doRunWithForkedJvm(String startClassName) throws MojoExecutionException, MojoFailureException {
    List<String> args = new ArrayList<>();
    addAgents(args);
    addJvmArgs(args);
    addClasspath(args);
    args.add(startClassName);
    addArgs(args);
    runWithForkedJvm((this.workingDirectory != null) ? this.workingDirectory : this.project.getBasedir(), args,
                     determineEnvironmentVariables());
}
private void addAgents(List<String> args) {
    File[] configuredAgents = determineAgents();
    if (configuredAgents != null) {
        if (getLog().isInfoEnabled()) {
            getLog().info("Attaching agents: " + Arrays.asList(configuredAgents));
        }
        for (File agent : configuredAgents) {
            args.add("-javaagent:" + agent);
        }
    }
    if (this.noverify) {
        args.add("-noverify");
    }
}
private File[] determineAgents() {
	return (this.agents != null) ? this.agents : this.agent;
}

private void addJvmArgs(List<String> args) {
    RunArguments jvmArguments = resolveJvmArguments();
    Collections.addAll(args, jvmArguments.asArray());
    logArguments("JVM argument(s): ", jvmArguments.asArray());
}
protected RunArguments resolveJvmArguments() {
    StringBuilder stringBuilder = new StringBuilder();
    if (this.systemPropertyVariables != null) {
        stringBuilder.append(this.systemPropertyVariables.entrySet().stream()
                .map((e) -> SystemPropertyFormatter.format(e.getKey(), e.getValue()))
                .collect(Collectors.joining(" ")));
    }
    if (this.jvmArguments != null) {
        stringBuilder.append(" ").append(this.jvmArguments);
    }
    return new RunArguments(stringBuilder.toString());
}
static class SystemPropertyFormatter {
    static String format(String key, String value) {
        if (key == null) {
            return "";
        }
        if (value == null || value.isEmpty()) {
            return String.format("-D%s", key);
        }
        return String.format("-D%s=\"%s\"", key, value);
    }
}

private void addClasspath(List<String> args) throws MojoExecutionException {
    try {
        StringBuilder classpath = new StringBuilder();
        for (URL ele : getClassPathUrls()) {
            if (classpath.length() > 0) {
                classpath.append(File.pathSeparator);
            }
            classpath.append(new File(ele.toURI()));
        }
        if (getLog().isDebugEnabled()) {
            getLog().debug("Classpath for forked process: " + classpath);
        }
        args.add("-cp");//指示classPath路径
        args.add(classpath.toString());
    }
    catch (Exception ex) {
        throw new MojoExecutionException("Could not build classpath", ex);
    }
}

private void addArgs(List<String> args) {
    RunArguments applicationArguments = resolveApplicationArguments();
    Collections.addAll(args, applicationArguments.asArray());
    logArguments("Application argument(s): ", applicationArguments.asArray());
}
protected RunArguments resolveApplicationArguments() {
    RunArguments runArguments = (this.arguments != null) ? new RunArguments(this.arguments)
            : new RunArguments(this.commandlineArguments);
    addActiveProfileArgument(runArguments);
    return runArguments;
}
private void addActiveProfileArgument(RunArguments arguments) {
    if (this.profiles.length > 0) {
        StringBuilder arg = new StringBuilder("--spring.profiles.active=");
        for (int i = 0; i < this.profiles.length; i++) {
            arg.append(this.profiles[i]);
            if (i < this.profiles.length - 1) {
                arg.append(",");
            }
        }
        arguments.getArgs().addFirst(arg.toString());
        logArguments("Active profile(s): ", this.profiles);
    }
}
private Map<String, String> determineEnvironmentVariables() {
    EnvVariables envVariables = resolveEnvVariables();
    logArguments("Environment variable(s): ", envVariables.asArray());
    return envVariables.asMap();
}
protected EnvVariables resolveEnvVariables() {
    return new EnvVariables(this.environmentVariables);
}

可以看出这整个过程都是拼凑java参数,不多说,我们来看真正的执行方法:runWithForkedJvm

protected abstract void runWithForkedJvm(File workingDirectory, List<String> args,
                                         Map<String, String> environmentVariables) throws MojoExecutionException, MojoFailureException;

@Override
protected void runWithForkedJvm(File workingDirectory, List<String> args, Map<String, String> environmentVariables)
        throws MojoExecutionException {
    int exitCode = forkJvm(workingDirectory, args, environmentVariables);
    if (exitCode == 0 || exitCode == EXIT_CODE_SIGINT) {
        return;
    }
    throw new MojoExecutionException("Application finished with exit code: " + exitCode);
}

private int forkJvm(File workingDirectory, List<String> args, Map<String, String> environmentVariables)
        throws MojoExecutionException {
    try {
        RunProcess runProcess = new RunProcess(workingDirectory, new JavaExecutable().toString());
        Runtime.getRuntime().addShutdownHook(new Thread(new RunProcessKiller(runProcess)));
        return runProcess.run(true, args, environmentVariables);
    }
    catch (Exception ex) {
        throw new MojoExecutionException("Could not exec java", ex);
    }
}

可以看出执行的是RunProcess#run:

public int run(boolean waitForProcess, Collection<String> args, Map<String, String> environmentVariables)
throws IOException {
    ProcessBuilder builder = new ProcessBuilder(this.command);
    builder.directory(this.workingDirectory);
    builder.command().addAll(args);
    builder.environment().putAll(environmentVariables);
    builder.redirectErrorStream(true);
    builder.inheritIO();
    try {
        Process process = builder.start();
        this.process = process;
        SignalUtils.attachSignalHandler(this::handleSigInt);
        if (waitForProcess) {
            try {
                return process.waitFor();
            }
            catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
                return 1;
            }
        }
        return 5;
    }
    finally {
        if (waitForProcess) {
            this.endTime = System.currentTimeMillis();
            this.process = null;
        }
    }
}

这个方法可以参考复用,还有JavaExecutable也可以复用

runWithMavenJvm(startClassName, resolveApplicationArguments().asArray());来看第二个分支
protected abstract void runWithMavenJvm(String startClassName, String... arguments)
throws MojoExecutionException, MojoFailureException;

protected void runWithMavenJvm(String startClassName, String... arguments) throws MojoExecutionException {
    IsolatedThreadGroup threadGroup = new IsolatedThreadGroup(startClassName);
    //LaunchRunner用于main的反射执行
    Thread launchThread = new Thread(threadGroup, new LaunchRunner(startClassName, arguments), "main");
    launchThread.setContextClassLoader(new URLClassLoader(getClassPathUrls()));
    launchThread.start();
    join(threadGroup);
    threadGroup.rethrowUncaughtException();
}

private void join(ThreadGroup threadGroup) {
    boolean hasNonDaemonThreads;
    //阻塞 等待所有线程执行完毕
    do {
        hasNonDaemonThreads = false;
        Thread[] threads = new Thread[threadGroup.activeCount()];
        //将活跃的线程加入到
        threadGroup.enumerate(threads);
        for (Thread thread : threads) {
            if (thread != null && !thread.isDaemon()) {
                try {
                    hasNonDaemonThreads = true;
                    thread.join();
                }
                catch (InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
    while (hasNonDaemonThreads);
}

这里从maven切出一个线程来执行应用程序,而fork模式则是采用客户端java拼装java命令来执行

<think>好的,我现在要解决用户提到的Spring Boot Maven Plugin版本3.2.4在运行时出现的错误。首先,我需要了解用户遇到的具体错误信息是什么,但用户没有提供详细的日志或错误描述。这种情况下,我需要考虑常见的错误类型,并给出一般性的解决步骤。 首先,常见的错误可能包括依赖问题、配置错误、插件兼容性或构建过程中的资源处理问题。例如,Maven可能在打包时找不到主类,或者插件版本与其他依赖不兼容。此外,内存不足或缓存问题也可能导致构建失败。 第一步,我应该建议用户检查Maven的构建日志,寻找具体的错误信息。比如,是否有“Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:3.2.4”这样的提示,或者类找不到、资源处理失败等错误。不同的错误需要不同的解决方案。 接下来,考虑依赖冲突的可能性。用户的项目中可能存在与Spring Boot 3.2.4不兼容的库版本。例如,Spring Boot 3.x需要Java 17或更高版本,如果用户还在使用Java 8,就会有问题。另外,Maven本身的版本是否支持该插件版本也需要确认,建议使用Maven 3.6.3或更高版本。 然后,清理Maven的本地仓库缓存可能解决因损坏的依赖导致的构建问题。用户可以通过执行mvn clean install -U来强制更新依赖。此外,检查pom.xml中的插件配置是否正确,特别是主类的配置和打包方式是否正确设置。 如果问题依然存在,可能需要调整插件的配置参数,比如跳过测试或调整内存设置。例如,添加<skipTests>true</skipTests>来排除测试阶段的问题,或者增加内存参数防止OOM错误。 最后,如果以上方法无效,建议用户降级插件版本到已知稳定的版本,如3.1.10,看看问题是否解决,这有助于判断是否是版本特定的bug。同时,查看官方文档和GitHub的Issue页面,寻找是否有已知的问题和解决方案。 在回答过程中,我需要确保步骤清晰,并提供具体的命令和配置示例,帮助用户逐步排查问题。同时,提醒用户检查Java版本、Maven配置等基础环境,这些往往是容易被忽视但关键的因素。另外,引用相关的参考资料,比如Activiti索引变更的例子,说明数据库或外部依赖可能带来的影响,尽管用户的问题主要集中在Maven插件上,但可能类似的依赖管理问题适用。</think>### Spring Boot Maven Plugin 3.2.4 运行时错误解决方案 #### 1. **检查错误日志** 首先需定位具体错误类型。运行以下命令获取详细日志: ```bash mvn spring-boot:run -X ``` 重点关注以下常见错误模式: - `ClassNotFoundException`:依赖缺失或版本冲突 - `Failed to execute goal`:插件配置错误 - `Resource handling failure`:资源过滤配置问题 #### 2. **验证环境配置** - **Java版本要求**:Spring Boot 3.x 需 Java 17+ 检查版本: ```bash java -version ``` - **Maven版本要求**:建议 Maven 3.6.3+ 升级命令: ```bash mvn -v ``` #### 3. **清理缓存与更新依赖** ```bash mvn clean install -U ``` `-U` 参数强制更新快照依赖,可解决因本地缓存损坏导致的问题[^1]。 #### 4. **检查插件配置** 在 `pom.xml` 中确认插件配置: ```xml <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>3.2.4</version> <configuration> <mainClass>com.example.Application</mainClass> <!-- 需替换为实际主类 --> </configuration> </plugin> </plugins> </build> ``` #### 5. **处理依赖冲突** 执行依赖树分析: ```bash mvn dependency:tree -Dverbose ``` 观察是否有 `omitted for conflict` 标记,例如: ``` [INFO] +- org.hibernate:hibernate-core:jar:6.4.1.Final [INFO] | \- org.jboss.logging:jboss-logging:jar:3.5.3.Final (omitted for conflict with 3.4.1.Final) ``` 通过 `<exclusions>` 排除冲突依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> <exclusions> <exclusion> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> </exclusion> </exclusions> </dependency> ``` #### 6. **调整插件参数** 针对特定错误类型尝试: - **跳过测试**: ```bash mvn spring-boot:run -DskipTests ``` - **内存设置**: ```xml <configuration> <jvmArguments>-Xmx1024m -XX:MaxPermSize=256m</jvmArguments> </configuration> ``` #### 7. **版本降级测试** 临时改用稳定版本验证: ```xml <version>3.1.10</version> <!-- LTS版本 --> ``` #### 8. **查看已知问题** 访问 [Spring Boot GitHub Issues](https://github.com/spring-projects/spring-boot/issues) 搜索关键词: ``` "spring-boot-maven-plugin 3.2.4" is:issue ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BingoXing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值