You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 17与Spring Boot 3.x可执行Jar的Security Manager问题求助

解决Spring Boot 3.x + Java 17下Security Manager导致可执行Jar类加载失败问题

问题场景

项目从Java 8/Spring Boot 2.x迁移至Java 17/Spring Boot 3.x,因内部需求必须保留自定义Security Manager。使用java -classpath <所有类和依赖> <主类>启动正常,但通过java -jar <可执行Jar>启动时出现大量Logger、Ignite等类找不到的异常,关闭Security Manager则无报错。自定义Security Manager启用代码如下:

log.warn("Enabling PlatformSecurityManager");
Policy policy = Policy.getPolicy();
PermissionCollection perm = policy.getPermissions(new CodeSource(null, (Certificate[]) null));
boolean canReplaceSecurityManager = perm.implies(new RuntimePermission("setSecurityManager"));
if (System.getSecurityManager() != null && !canReplaceSecurityManager) {
  //we have to do the check like this because it will be from a different classloader
  if (!(System.getSecurityManager().getClass().getName().equals(PlatformSecurityManager.class.getName()))) {
    throw new RuntimeException(
        "You have started the JVM with a security manager that doesn't allow me to set a new one!");
  }
  //else another platform application has specified the security manager... so we should be ok
} else {
  if (System.getProperty("java.security.policy") == null) {
    log.warn("java.security.policy Not found");
    //load up allow all policy
    log.info("Enabling AllPermission for the platform security manager");
    PlatformSecurityPolicy platformPolicy = new PlatformSecurityPolicy();
    platformPolicy.addPermission(new AllPermission());
    Policy.setPolicy(platformPolicy);
  }

  log.warn("Enabled PlatformSecurityManager");
  System.setSecurityManager(new PlatformSecurityManager(false));
}

核心原因

Spring Boot可执行Jar使用LaunchedURLClassLoader加载BOOT-INF/lib下的嵌套依赖,与普通classpath启动的类加载逻辑存在差异。结合Java 17中Security Manager的废弃特性,当前自定义Policy的权限覆盖范围未适配该类加载器场景,导致读取嵌套Jar资源时权限不足,触发类找不到异常。

解决思路

1. 补全自定义Policy的类加载相关权限

当前代码添加的AllPermission可能因类加载器上下文问题未生效到LaunchedURLClassLoader,需显式补充类加载和Jar资源读取权限:

if (System.getProperty("java.security.policy") == null) {
    log.warn("java.security.policy Not found");
    log.info("Enabling permissions for platform security manager");
    PlatformSecurityPolicy platformPolicy = new PlatformSecurityPolicy();
    // 保留全权限兜底
    platformPolicy.addPermission(new AllPermission());
    // 补充Jar资源读取权限
    platformPolicy.addPermission(new URLPermission("jar:*", "read"));
    // 补充本地Jar文件读取权限
    platformPolicy.addPermission(new FilePermission("<<ALL FILES>>", "read"));
    // 补充类加载相关权限
    platformPolicy.addPermission(new RuntimePermission("getClassLoader"));
    platformPolicy.addPermission(new RuntimePermission("setContextClassLoader"));
    Policy.setPolicy(platformPolicy);
}

2. 调整Security Manager启动时机

Spring Boot 3.x启动流程中,过早设置Security Manager可能干扰LaunchedURLClassLoader初始化,可尝试在应用启动完成后再初始化:

public static void main(String[] args) {
    // 先启动Spring Boot应用
    ConfigurableApplicationContext context = SpringApplication.run(MainClass.class, args);
    // 再初始化Security Manager
    initSecurityManager();
}

private static void initSecurityManager() {
    // 放入原有的Security Manager初始化代码
}

3. 排查具体权限缺失

重写自定义Security Manager的checkPermission方法,打印被拒绝的权限和调用栈,精准定位缺失项:

public class PlatformSecurityManager extends SecurityManager {
    // 原有构造方法和逻辑

    @Override
    public void checkPermission(Permission perm) {
        try {
            super.checkPermission(perm);
        } catch (SecurityException e) {
            System.err.println("Permission denied: " + perm);
            e.printStackTrace();
            throw e;
        }
    }
}

4. 改用JVM启动参数指定Security Manager

避免代码动态设置的上下文问题,直接通过JVM参数强制指定:

java -Djava.security.manager=com.your.package.PlatformSecurityManager \
     -Djava.security.policy==/path/to/your/policy-file.policy \
     -jar your-executable.jar

注意java.security.policy参数使用两个等号,表示强制替换系统默认Policy而非追加。

5. 适配Java 17的CodeSource逻辑

Java 17对null CodeSource的权限处理行为变化,尝试使用当前类的CodeSource替代:

// 替换原有的null CodeSource
CodeSource currentCodeSource = MainClass.class.getProtectionDomain().getCodeSource();
PermissionCollection perm = policy.getPermissions(currentCodeSource);

内容的提问来源于stack exchange,提问作者Nishant Modi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 00:20:42