java - 可执行 jar 中的 Apache POI
问题描述
我的程序成功运行 Apache POI 功能来读取 Excel 文件。当我使用 java 类名运行它时它工作正常。当我打包为可执行 jar 时,它不起作用。这是我不断收到的错误消息:
java -jar some.jar
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/poi/ss/usermodel/Row
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException: org.apache.poi.ss.usermodel.Row
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
当我正常运行它时它工作正常,例如
java a.e
我从阅读堆栈溢出中知道,以确保我拥有
poi-ooxml
和xmlbeans
. (20688851, 15831591)
这是我的可执行 jar 根目录中的 jar 文件。
5924600 Wed Sep 12 13:02:26 CDT 2018 poi-ooxml-schemas-3.17.jar
1479023 Wed Sep 12 13:02:26 CDT 2018 poi-ooxml-3.17.jar
1390360 Tue Oct 02 13:04:14 CDT 2018 poi-scratchpad-3.17.jar
313359 Tue Oct 02 13:17:34 CDT 2018 dom4j.jar
25863 Tue Oct 02 13:19:46 CDT 2018 stax-api.jar
1950905 Wed Sep 12 13:02:26 CDT 2018 poi-3.10-FINAL-20140208.jar
2730866 Tue Oct 02 12:43:34 CDT 2018 xmlbeans-2.6.0.jar
这是我演示问题的最小测试用例。
package a;
import java.io.*;
import java.lang.*;
import java.lang.reflect.*;
import java.util.*;
public class e {
static PrintWriter F;
static FileInputStream ConfigurationFile;
static String iSheet = "TAB2";
private static final String strResourceName = "11in35tr.xls";
static
{
java.io.InputStream streamData = null;
try
{
streamData=a.e.class.getResourceAsStream(strResourceName);
}
catch(NullPointerException e)
{
System.out.println("Unable to load the resource stream for '" + strResourceName + "'");
assert false;
}
System.out.println (" stream Data |" + streamData+"|");
org.apache.poi.hssf.usermodel.HSSFWorkbook workbook = null;
try
{
workbook = new org.apache.poi.hssf.usermodel.HSSFWorkbook(streamData);
}
catch(java.io.IOException e)
{
System.out.println("Unable to create a HSSFWorkbook for the stream. Is it really an Excel file?");
assert false;
}
String Sheet;
org.apache.poi.hssf.usermodel.HSSFSheet sheet = workbook.getSheet(iSheet);
if(sheet == null) {
System.out.println("While we were able to open the resource as an Excel file, it doesn't appear to contain sheet " + sheet.toString() + " as specified in the config file");
}
for(int iCurRow = 0;iCurRow<3;iCurRow++)
{
org.apache.poi.ss.usermodel.Row rowCur = sheet.getRow(iCurRow);
if(rowCur == null)
{
System.out.println("We're supposed to get a row title from row " +
Integer.toString(iCurRow) + " in sheet " + iSheet + ", but that row doesn't exist");
break;
}
for (int iCol=0;iCol<3;iCol++) {
org.apache.poi.ss.usermodel.Cell
cellWithTitle = rowCur.getCell(iCol);
if(cellWithTitle == null)
{
System.out.println("We're supposed to get a row title from cell " + Integer.toString(iCol) + " in row " + Integer.toString(iCurRow) + " in sheet " + iSheet + ", but that column doesn't appear to exist in the specified sheet.");
break;
}
String strNewRowTitle = cellWithTitle.toString();
System.out.println("Created row: '" + strNewRowTitle + "'");
}
} // for
} // end of static
static void Init () throws java.io.IOException {
ConfigurationFile = new FileInputStream ("config.in");
F = new PrintWriter (new FileOutputStream ("config.out"));
}
public static void main (String args[]) throws IOException {
Init();
F.close();
}
}
不幸的是,这些都不起作用。首先,我更新了 manifest.txt 文件。(如..所示)
Main-Class: a.c
Class-path: poi-ooxml-schemas-3.17.jar poi-ooxml-3.17.jar poi-scratchpad-3.17.jar dom4j.jar stax-api.jar poi-3.10-FINAL-2014028.jar xmlbeans-2.6.0.jar
然后,我尝试了命令
java -classpath *.jar -jar some.jar
java -classpath "poi-ooxml-schemas-3.17.jar:poi-ooxml-3.17.jar:poi-scatchpad-3.17.jar:dom4.jar:stax-api.jar:poi-3.10-FINAL-2014028.jar:xmlbeans-2.6.0.jar" -jar some.jar
我的理解是,当我们使用可执行 jar 时,会忽略 -classpath。
因此,在下载了我在原始帖子中列出的一组 jar 之后,我确实尝试了以下变体。
set CLASSPATH=".;poi-ooxml-schemas-3.17.jar;poi-ooxml-3.17.jar;poi-scatchpad-3.17.jar;dom4.jar;stax-api.jar;poi-3.10-FINAL-2014028.jar;xmlbeans-2.6.0.jar"
echo %CLASSPATH%
java a.e
他们以同样的方式失败。但是,我可以在 Linux 系统上正常运行该程序。因此,显然,在 LINUX 系统上 POI 需要的东西在 Windows 计算机上没有。
(注意 ae 在 LINUX 上运行良好。它不能在 PC== 上运行,所以我在 LINUX 中设置的那个环境需要一些东西,但不知道那是什么。但是,我也再次检查了将 ae 放入一个可执行的 jar 并在相同的 LINUX 环境中运行它。它会产生同样的问题。)
当然,我也尝试从poi.apache.org
zip 文件中获取新的 4.0 下载并包括六个 jar 文件poi-bin-4.0.0...zip
)
解决方案
你有2个可能性
将这些 jar 包含在您的内部并在 META-INF/MANIFEST.MF 中设置类路径
Manifest-Version: 1.0
Class-Path: file1.jar file2.jar file3.jar
或在您调用 java 时将这些 jars 添加到类路径
java -classpath \path_to_jars\*.jar your.package.YourMainClass
推荐阅读
- docker - 为什么多个 docker 容器可以有相同的内部端口
- python - 为什么 __repr__ 不能是 __init__ 中定义的属性?
- angular - 即使创建新项目,角度问题也不指向 src 文件夹
- javascript - 动态字段未保存在数据库中
- reactjs - React.lazy 与 react-router 3
- price - 谷歌语音转文本的成本?
- pyenv - pyenv 在执行所述模块时在终端中打印模块
- javascript - 条件适用时使用 yup 覆盖表单中的值
- angular - 类型“{}”Angular RxJs 上不存在属性“过滤器”
- xslt - 检查 xslt 中的地图是否为空