当我在IDE中运行Java代码时,它成功运行。当我构建一个jar文件并从命令行运行它时,我收到一个“java。lang.ExceptionInInitializerError”。我怀疑我的ApacheAnt构建脚本有问题,但我不确定。
下面是我的极度简化的代码(是的,我知道我没有在失败时完全关闭DB连接,但这是我创建的一些小东西,只是为了获得最简单的代码版本,我仍然可以展示错误):
package com.company.TestApp.TestProj;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class Main {
public Main() {
super();
}
public static void main(String[] args) {
Main main = new Main();
main.run();
}
public void run() {
System.out.println("Starting");
try {
Class.forName("oracle.jdbc.OracleDriver");
Connection db = DriverManager.getConnection(connectionString, schema, password);
if (db.isValid(10)) {
System.out.println("Connected");
}
else {
System.out.println("Not connected");
throw new Exception("Not connected");
}
String sql = "SELECT * FROM dual";
Statement statement = db.createStatement();
ResultSet rs = statement.executeQuery(sql);
while (rs.next()) {
System.out.println("Record");
}
rs.close();
statement.close();
db.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
我的非常简化的Apache Ant构建脚本是:
<project name="test" basedir="." default="main">
<property name="src.dir" value="src"/>
<property name="build.dir" value="build"/>
<property name="classes.dir" value="${build.dir}/classes"/>
<property name="jar.dir" value="${build.dir}/jar"/>
<property name="main-class" value="com.company.TestApp.TestProj.Main"/>
<property name="lib.dir" value="../lib"/>
<path id="classpath">
<fileset dir="${lib.dir}" includes="**/*.jar"/>
</path>
<target name="clean">
<delete dir="${build.dir}"/>
</target>
<target name="compile">
<mkdir dir="${classes.dir}"/>
<javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath"/>
</target>
<target name="jar" depends="compile">
<mkdir dir="${jar.dir}"/>
<jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
<fileset dir="${jar.dir}">
<include name="**/*.class"/>
</fileset>
<zipfileset src="${lib.dir}/ojdbc7.jar">
<include name="**/*.class"/>
</zipfileset>
<manifest>
<attribute name="Main-Class" value="${main-class}"/>
</manifest>
</jar>
</target>
<target name="run" depends="jar">
<java fork="true" classname="${main-class}">
<classpath>
<path refid="classpath"/>
<path location="${jar.dir}/${ant.project.name}.jar"/>
</classpath>
</java>
</target>
<target name="clean-build" depends="clean,jar"/>
<target name="main" depends="clean,run"/>
</project>
我的IDE是JDeveloper 12。1.3.0.0.我的JAVA_HOME和路径设置为JDK 1。8.0_291.我的Oracle DB是19。13.0.0.0
当我从IDE运行程序时,我得到了预期的结果:
Starting
Connected
Record
当我用“java -jar测试”从命令行运行jar时。jar”的输出是:
Starting
Connected
Exception in thread "main" java.lang.ExceptionInInitializerError
at oracle.jdbc.driver.OracleStatement.configureRowData(OracleStatement.java:760)
at oracle.jdbc.driver.OracleStatement.<init>(OracleStatement.java:696)
at oracle.jdbc.driver.T4CStatement.<init>(T4CStatement.java:1152)
at oracle.jdbc.driver.T4CDriverExtension.allocateStatement(T4CDriverExtension.java:46)
at oracle.jdbc.driver.PhysicalConnection.createStatement(PhysicalConnection.java:3914)
at oracle.jdbc.driver.PhysicalConnection.createStatement(PhysicalConnection.java:3874)
at com.company.TestApp.TestProj.Main.run(Main.java:34)
at com.company.TestApp.TestProj.Main.main(Main.java:15)
Caused by: java.lang.NullPointerException
at oracle.jdbc.driver.DynamicByteArray$1.run(DynamicByteArray.java:540)
at java.security.AccessController.doPrivileged(Native Method)
at oracle.jdbc.driver.DynamicByteArray.<clinit>(DynamicByteArray.java:535)
... 8 more
Java JDK18.0_291,但我在其他不同版本的Java机器上尝试过,收到同样的错误。我用的是OJDBC 7。JDeveloper附带的jar。
2条答案
按热度按时间cidc1ykv1#
要让fat JAR使用
java -jar test.jar
运行,需要对Ant脚本做一个小的修改。更改此:
对此:
原因是:在OracleJDBCJAR中不仅仅有
.class
文件。还有(例如)属性文件,如
和其他文件。
我不知道哪个 * 特定 * 丢失的文件是你的异常的根本原因。我只是执行了一个包含所有内容的构建。
题外话:
您可能已经知道以下内容-但对于未来的访问者这个问题。..
还值得注意的是,JDBC文件包含一个名为
java.sql.Driver
的文件(在META-INF/services
中),该文件包含Oracle驱动程序类的名称:通常,这用于自动加载Oracle JDBC驱动程序-所以不需要下面的代码行:
然而,这是通过扫描库JAR文件来实现的--因为您的应用程序“胖”jar中不再有Oracle JAR文件,所以您仍然需要上面的代码行。
这是目前仍然需要这行代码以避免
No suitable driver found
异常的相对罕见的情况之一。m2xkgtsf2#
一个同事可以通过手动指定classpath来让它工作:
我不明白为什么需要这样做,但我怀疑我没有正确地在ant脚本中包含ojdbc jar文件。如果有人能向我解释解决这个问题的方法,将不胜感激!