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

JDK16及以上版本如何在自有Java代码中调用Java工具类静态方法

问题错误原因

Unable to make public static void sun.tools.jar.Main.main(java.lang.String[]) accessible: module jdk.jartool does not "exports sun.tools.jar" to unnamed module @46d21ee0

该报错是JDK 16及以上版本对JDK内部API强封装导致的:JDK 9引入的JPMS模块化系统将sun.tools.jar.Main归属到jdk.jartool模块,且该类属于模块内部未导出的非公开API,JDK 16默认禁止类路径下的未命名模块访问这类内部API,直接反射调用就会触发权限错误。

可行解决方案

方案1:子进程调用官方工具命令(生产环境首选,无兼容性风险)

放弃直接在代码中反射调用内部API的实现方式,改为通过ProcessBuilder启动子进程执行JDK自带的jar、javac等官方命令,该方案兼容所有JDK版本,不依赖任何内部实现。
参考代码示例:

// jar 命令调用示例
public int runJarCommand(String[] args) throws IOException, InterruptedException {
    // 构造命令,args为原本传入sun.tools.jar.Main的参数
    ProcessBuilder pb = new ProcessBuilder();
    pb.command("jar", args);
    // 可配置工作目录、IO输出规则
    pb.inheritIO();
    Process p = pb.start();
    return p.waitFor();
}

执行后通过返回码判断执行结果,0为成功,非0为失败。

方案2:添加JVM启动参数临时开放权限(适合临时调试)

如果暂时无法修改代码,可以在启动应用时添加JVM启动参数,手动开放对应模块的导出权限:

--add-exports jdk.jartool/sun.tools.jar=ALL-UNNAMED

如果同时调用了Java编译器的内部类,追加对应模块的导出参数:

--add-exports jdk.compiler/com.sun.tools.javac.*=ALL-UNNAMED

该方案属于临时适配方案,后续更高版本JDK可能完全封禁内部API访问权限,存在长期兼容风险。

方案3:使用JDK公开API实现对应能力

  • 调用Java编译器可直接使用javax.tools.ToolProvider.getSystemJavaCompiler()公开API,不需要依赖内部的javac实现类。
  • 打包jar文件可以使用java.util.jar.JarOutputStream等公开类自行实现打包逻辑,完全脱离对sun.tools.jar的依赖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 13:57:05