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

Java调用PlantUML生成UML图时报IllegalAccessError错误

问题描述

使用Java编写代码生成简单PlantUML图形时,程序运行持续抛出错误,相关实现代码如下:

实现代码

public class PlantUMLDemoMain {
    public static void main(String[] args) throws Exception {
        generateFromStringSource(new File("from-string.png"));
        generateFromApi(new File("from-api.png"));
    }

    private static void generateFromApi(File file) throws IOException {
        // 1. setup:
        SequenceDiagramFactory f = new SequenceDiagramFactory();
        SequenceDiagram diagram = f.createEmptyDiagram();

        // 2. Build the diagram:
        // "Bob -> Alice : hello"
        // See net.sourceforge.plantuml.sequencediagram.command.CommandArrow#executeArg
        Display bobD = Display.getWithNewlines("Bob");
        Participant bobP = diagram.getOrCreateParticipant("Bob", bobD);
        Display aliceD = Display.getWithNewlines("Alice");
        Participant aliceP = diagram.getOrCreateParticipant("Alice", aliceD);

        Display label = Display.getWithNewlines("hello");
        ArrowConfiguration config = ArrowConfiguration.withDirectionNormal();

        Message msg = new Message(bobP, aliceP, label, config, diagram.getNextMessageNumber());

        checkState(null == diagram.addMessage(msg));

        // 3. Output the diagram
        // See net.sourceforge.plantuml.SourceStringReader#generateImage
        diagram.makeDiagramReady();
        checkState(1 == diagram.getNbImages());
        try (OutputStream os = new FileOutputStream(file)) {
            ImageData imageData = diagram.exportDiagram(os, 0, new FileFormatOption(FileFormat.PNG));
            System.out.println("generateFromApi: " + diagram.getDescription().getDescription());
        }
    }

    private static void generateFromStringSource(File file) throws IOException {
        String source = "@startuml\n";
        source += "Bob -> Alice : hello\n";
        source += "@enduml\n";

        StringBuffer stringBuffer = new StringBuffer();

        SourceStringReader reader = new SourceStringReader(source);
        // Write the first image to "png"
        String desc = reader.generateImage(file);
        // Return a null string if no generation
        System.out.println("generateFromStringSource: " + desc);
    }
}

运行异常信息

Error: Exception in thread "main" java.lang.IllegalAccessError: class net.sourceforge.plantuml.png.PngIOMetadata (in unnamed module @0x9597028) cannot access class com.sun.imageio.plugins.png.PNGMetadata (in module java.desktop) because module java.desktop does not export com.sun.imageio.plugins.png to unnamed module @0x9597028
    at net.sourceforge.plantuml.png.PngIOMetadata.writeWithMetadata(PngIOMetadata.java:60)
    at net.sourceforge.plantuml.png.PngIO.write(PngIO.java:86)
    at net.sourceforge.plantuml.png.PngIO.write(PngIO.java:80)
    at net.sourceforge.plantuml.ugraphic.g2d.UGraphicG2d.writeImageTOBEMOVED(UGraphicG2d.java:219)
    at net.sourceforge.plantuml.ugraphic.ImageBuilder.writeImageInternal(ImageBuilder.java:249)
    at net.sourceforge.plantuml.ugraphic.ImageBuilder.writeImageTOBEMOVED(ImageBuilder.java:171)
    at net.sourceforge.plantuml.sequencediagram.graphic.SequenceDiagramFileMakerPuma2.createOne(SequenceDiagramFileMakerPuma2.java:234)
    at net.sourceforge.plantuml.sequencediagram.SequenceDiagram.exportDiagramInternal(SequenceDiagram.java:222)
    at net.sourceforge.plantuml.UmlDiagram.exportDiagramNow(UmlDiagram.java:236)
    at net.sourceforge.plantuml.AbstractPSystem.exportDiagram(AbstractPSystem.java:127)
    at net.sourceforge.plantuml.SourceStringReader.generateImage(SourceStringReader.java:124)
    at net.sourceforge.plantuml.SourceStringReader.generateImage(SourceStringReader.java:111)
    at net.sourceforge.plantuml.SourceStringReader.generateImage(SourceStringReader.java:101)
    at scr.graphviz.sk.PlantUMLDemoMain.generateFromStringSource(PlantUMLDemoMain.java:66)
    at scr.graphviz.sk.PlantUMLDemoMain.main(PlantUMLDemoMain.java:23)

已尝试操作

  • 检索到同类问题反馈称使用旧版本PlantUML可解决,已获取对应旧版本jar包,但不清楚如何正确配置替换
  • 曾尝试解析jar包内引用的依赖版本并在Maven中添加对应依赖,配置后问题仍未解决
错误根因

该异常是Java 9及以上版本模块化系统访问限制导致的:当前使用的PlantUML版本直接调用了JDK内部非公开APIcom.sun.imageio.plugins.png.PNGMetadata,模块化环境下java.desktop模块默认不会向未命名模块(即业务代码及引入的第三方jar包)开放这个内部包的访问权限,因此抛出非法访问错误。

可行解决方案
  • 方案1:添加JVM启动参数(无需修改依赖,成本最低)
    启动程序时追加如下VM参数,直接开放对应内部包的访问权限即可解决问题:
    --add-exports java.desktop/com.sun.imageio.plugins.png=ALL-UNNAMED
    
    如果在IntelliJ IDEA等IDE中运行,直接在运行配置的「VM options」输入框填入上述参数即可;如果通过Maven命令运行,可在exec-maven-plugin、maven-surefire-plugin等插件的配置项中追加该参数。
  • 方案2:正确替换为兼容的PlantUML旧版本
    之前替换依赖失败,基本都是Maven依赖冲突导致其他组件传递引入的高版本PlantUML没有被排除,实际运行时加载的还是存在兼容问题的版本,正确操作步骤如下:
    1. 在项目根目录执行mvn dependency:tree,在输出的依赖树中找到所有引入PlantUML的依赖路径,对这些依赖全部添加<exclusion>规则排除传递引入的PlantUML包
    2. 在pom.xml中显式引入适配JDK8的PlantUML稳定版本(推荐1.2020.2版本,该版本不存在模块化兼容问题),配置示例:
    <dependency>
        <groupId>net.sourceforge.plantuml</groupId>
        <artifactId>plantuml</artifactId>
        <version>1.2020.2</version>
    </dependency>
    
    1. 执行mvn clean install命令刷新依赖,再次检查依赖树确认项目中仅存在你引入的指定版本PlantUML,无其他版本残留后再运行程序即可。
  • 方案3:切换运行环境为JDK8
    JDK8未引入模块化系统,不存在内部API访问限制,直接将项目的运行时JDK切换为JDK8版本,无需修改任何代码或依赖即可正常运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 21:06:23