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

使用Ant构建Jar查询Oracle DB时出现ExceptionInInitializerError,但IDE运行正常

问题:Jar包运行Oracle查询抛出ExceptionInInitializerError,IDE运行正常

我的Java代码在JDeveloper 12.1.3.0.0中能正常查询Oracle 19.13.0.0.0数据库,但通过Apache Ant构建Jar包后,命令行运行时执行查询的代码抛出java.lang.ExceptionInInitializerError。


简化代码

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();
        }
    }
}

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>

环境信息

  • JDK版本:1.8.0_291(JAVA_HOME及PATH已配置)
  • Oracle驱动:ojdbc7.jar(来自JDeveloper)

IDE运行结果

Starting
Connected
Record

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

解决方案

问题出在Ant构建脚本的Jar打包步骤:你仅将ojdbc7.jar的class文件打包进了自己的Jar,但Oracle驱动Jar里除了class文件,还有必要的配置文件和资源文件(比如oracle/jdbc/driver/OracleDriver.properties、本地化资源等),这些文件缺失导致初始化失败。

修复步骤

  1. 修改Ant的Jar打包目标,两种可选方案:

    • 方案一:分离依赖,通过Manifest声明类路径
      调整后的jar目标:
      <target name="jar" depends="compile">
          <mkdir dir="${jar.dir}"/>
          <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
              <manifest>
                  <attribute name="Main-Class" value="${main-class}"/>
                  <!-- 声明依赖的ojdbc7.jar路径,需与运行时实际位置匹配 -->
                  <attribute name="Class-Path" value="../lib/ojdbc7.jar"/>
              </manifest>
          </jar>
      </target>
      
    • 方案二:构建包含所有依赖的可执行Jar
      打包ojdbc7.jar的所有内容(包括资源文件),而不是仅class:
      <target name="jar" depends="compile">
          <mkdir dir="${jar.dir}"/>
          <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
              <!-- 打包ojdbc7.jar的全部内容 -->
              <zipfileset src="${lib.dir}/ojdbc7.jar"/>
              <manifest>
                  <attribute name="Main-Class" value="${main-class}"/>
              </manifest>
          </jar>
      </target>
      
  2. 运行时确保依赖可用

    • 若用分离依赖方案,运行时需保证ojdbc7.jar在Manifest声明的路径下,或通过命令指定完整类路径:java -cp your.jar:../lib/ojdbc7.jar com.company.TestApp.TestProj.Main
    • Ant的run目标无需修改,它已引用完整classpath,包含lib目录下的Jar。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 19:55:14