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
相关产品推荐
相关产品推荐

