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

Java 10环境下使用Apache POI读取Excel时出现报错问题

Java 10环境下Apache POI Excel解析程序报错无法读取文件的解决方案

我来帮你排查这个Java 10下Apache POI报错的问题,结合你的场景和代码,大概率是Java 9引入的**模块系统(JPMS)**在Java 10中兼容性限制更严格导致的,下面是具体的分析和解决方案:

问题背景回顾

你用Java 9结合最新版Apache POI开发了Excel解析程序,导出jar后本地运行正常,但切换到Java 10环境就大量报错无法读取文件;Java 9环境下仅弹出警告但程序可正常执行。相关核心代码如下:

@FXML public void handleFileButtonClick() throws Exception {
    FileChooser fileChooser = new FileChooser();
    fileChooser.setTitle("Please Select a SpreadSheet");
    FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("Excel files (*.xlsx)", "*.xlsx");
    fileChooser.getExtensionFilters().add(extFilter);
    File file = fileChooser.showOpenDialog(mainGridPane.getScene().getWindow());
    if (file != null) {
        open(file);
    } else {
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.setTitle("File Not Found");
        alert.setContentText("File was not found or cannot be read.");
        alert.showAndWait();
    }
}

private void open(File file) throws Exception {
    XSSFWorkbook workbook = new XSSFWorkbook(file);
    XSSFSheet spreadSheet = workbook.getSheetAt(0);
    Iterator<Row> rowIterator = spreadSheet.iterator();
    rowIterator.next();
    rowIterator.next();
    rowIterator.next();
    rowIterator.next();
    rowIterator.next();
    while (rowIterator.hasNext()) {
        row = (XSSFRow) rowIterator.next();
        Iterator<Cell> cellIterator = row.cellIterator();
        Job job = new Job();
        while (cellIterator.hasNext()) {
            Cell cell = cellIterator.next();
            DataFormatter dataFormatter = new DataFormatter();
            String cellStringValue = dataFormatter.formatCellValue(cell);
            switch (cell.getColumnIndex()) {
                case 0:
                case 1:
                    break;
                case 2:
                    if (!cellStringValue.equals("")) {
                        String[] date = cellStringValue.split("/");
                        LocalDate newDate = LocalDate.of(2000 + Integer.parseInt(date[2]), Integer.parseInt(date[0]), Integer.parseInt(date[1]));
                        job.setStartDate(newDate);
                    }
                    break;
                case 3:
                    if (!cellStringValue.equals("")) {
                        String[] date2 = cellStringValue.split("/");
                        LocalDate newDate2 = LocalDate.of(2000 + Integer.parseInt(date2[2]), Integer.parseInt(date2[0]), Integer.parseInt(date2[1]));
                        job.setEndDate(newDate2);
                    }
                    break;
                case 4:
                    if (!cellStringValue.equals("")) {
                        job.setTotalDaysPaid(Integer.parseInt(cellStringValue));
                    }
                    break;
                case 5:
                    break;
                case 6:
                    if (!cellStringValue.equals("")) {
                        String[] date3 = cellStringValue.split("/");
                        LocalDate newDate3 = LocalDate.of(2000 + Integer.parseInt(date3[2]), Integer.parseInt(date3[0]), Integer.parseInt(date3[1]));
                        job.setNextYearStart(newDate3);
                    }
                    break;
                case 7:
                    if (!cellStringValue.equals("")) {
                        String[] date4 = cellStringValue.split("/");
                        LocalDate newDate4 = LocalDate.of(2000 + Integer.parseInt(date4[2]), Integer.parseInt(date4[0]), Integer.parseInt(date4[1]));
                        job.setNextYearEnd(newDate4);
                    }
                    break;
                default:
                    break;
            }
        }
        if (job.getStartDate() != null) {
            jobs.add(job);
        }
    }
    workbook.close();
}

核心原因分析

Java 9开始引入了模块系统,将JDK拆分为多个模块,而Java 10对模块的访问限制更加严格。Apache POI依赖的一些JDK模块(比如java.xml.bind、java.activation)在Java 9+中是可选模块,默认不会被加载;同时POI内部可能使用了反射访问JDK内部类,这在Java 10的模块系统下会被拦截,导致类加载失败或权限错误。

解决方案步骤

1. 确认并升级Apache POI版本

确保你使用的Apache POI版本完全兼容Java 10:

  • POI 4.0.0及以上版本对Java 9+的模块系统支持更完善,如果你的版本低于这个,建议升级到最新稳定版(比如POI 5.x系列,注意POI 5.x需要Java 8+,完全兼容Java 10)。
  • 检查你的依赖管理(Maven/Gradle)配置,确保poi、poi-ooxml、poi-ooxml-schemas等核心依赖版本一致。

2. 调整Java 10的运行参数

如果你的程序是非模块化jar(没有module-info.java),运行时需要添加以下参数来开放必要的模块和权限:

java --add-modules java.xml.bind,java.activation --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED -jar your-excel-app.jar
  • --add-modules:加载POI依赖的可选JDK模块
  • --add-opens:开放POI需要反射访问的JDK内部类权限

3. 检查jar包的依赖完整性

确保你的可执行jar包包含了所有POI的依赖:

  • 如果用Maven的maven-assembly-plugin或maven-shade-plugin打包,要确保所有POI相关的依赖都被正确打包进去,避免缺失依赖导致的类找不到错误。
  • 手动解压jar包,检查是否包含org.apache.poi开头的包,以及com.microsoft.schemas、org.openxmlformats等POI-OOXML依赖的包。

4. (可选)添加模块声明(如果使用模块化开发)

如果你的程序是模块化的(有module-info.java),需要在模块声明中添加对POI模块的依赖:

module your.excel.app {
    requires org.apache.poi.poi;
    requires org.apache.poi.poi.ooxml;
    requires javafx.controls;
    requires javafx.fxml;
    // 开放必要的包给POI反射访问
    opens your.package.to.open to org.apache.poi.poi;
}

验证方案

按照上述步骤调整后,重新打包并在Java 10环境下运行,应该可以解决报错问题。如果还有错误,可以查看具体的报错信息(比如类找不到、权限拒绝),再针对性调整运行参数或依赖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 03:28:38