Eclipse运行正常但JAR包异常:Class.forName()未抛异常却跳至finally块
问题详情
程序在Eclipse环境运行完全正常,但打包成JAR文件执行时出现以下异常:
- 执行
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver")后无可见异常抛出,直接跳转至finally块 - 最终在
con.close()(代码第449行)触发java.lang.NullPointerException - 测试输入错误驱动类名时,会正常抛出
ClassNotFoundException,说明驱动类可被正确加载
运行输出对比
Eclipse运行输出
Finding class...
Getting connection for log population...
Got connection for log population...
In finally block...
Finished.
JAR运行输出
C:\me\myProgram>java -cp MyJar.jar;mssql-jdbc-12.4.0.jre11.jar com.me.myProgram.Main Finding class... In finally block... Exception in thread "main" java.lang.NullPointerException at com.me.myProgram.logResults(Comparison.java:449) at com.me.myProgram.run(Comparison.java:547) at com.me.myProgram.Main.main(Main.java:13)
错误类名测试输出
D:\me\myProgram>java -cp MyJar.jar;mssql-jdbc-12.4.0.jre11.jar com.me.myProgram.Main Finding class... com.microsoft.sqlserver.jdbc.SQLServerDrive java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDrive at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ...
相关代码片段(第449行为con.close())
Connection con = null; try { System.out.println("Finding class..."); Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); System.out.println("Getting connection for log population..."); con = DriverManager.getConnection(url, user, pass); System.out.println("Got connection for log population..."); // 业务逻辑代码 } catch (Exception e) { // 原异常处理逻辑(未输出异常信息) } finally { try { con.close(); // 第449行,触发NPE } catch (SQLException e) { e.printStackTrace(); } }
解决步骤
1. 修复异常捕获,暴露真实错误
问题根源是Class.forName或getConnection抛出了异常,但原catch块未输出任何异常信息,导致看起来像“无异常跳转”。Eclipse运行正常是因为连接参数(URL、用户名、密码)正确,而JAR运行时参数不符。
修改catch块,强制打印完整异常栈:
catch (Exception e) { e.printStackTrace(); // 或写入日志,确保异常信息被输出 }
执行JAR后即可看到真正的异常原因(比如URL格式错误、数据库拒绝连接、用户名密码无效等)。
2. 给finally块增加非空判断
无论连接是否成功创建,都要先检查con是否为null再调用close(),直接避免NPE:
finally { try { if (con != null) { con.close(); } } catch (SQLException e) { e.printStackTrace(); } }
3. 验证JAR运行环境的连接参数
- 检查JAR运行时的数据库URL、用户名、密码是否与Eclipse中一致
- 若使用外部配置文件,确保文件路径正确或已打包进JAR
- 确认数据库服务器允许JAR所在机器的IP访问
- 核对SQL Server JDBC URL格式(示例:
jdbc:sqlserver://localhost:1433;databaseName=testDB;encrypt=true;trustServerCertificate=true)
4. 可选:移除手动驱动加载
JDBC 4.0及以上版本会自动加载驱动类,可移除Class.forName调用,简化代码:
// 移除该行代码 // Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); con = DriverManager.getConnection(url, user, pass);
内容的提问来源于stack exchange,提问作者patricio2626
相关产品推荐
相关产品推荐

