在開發與部署 DB2 UDB Java 存儲過程時,開發人員經常會遇到各種錯誤碼。本文承接上篇,繼續深入剖析 SQL4304、SQL4306、SQL20200、SQL20201、SQL20204、SQL0449、SQL0444、SQL0440、SQL1042、SQL1131 等常見錯誤的成因、診斷方法與具體修正步驟,並提供完整的代碼示例與日誌分析技巧,助您快速定位並解決問題。
當 CREATE PROCEDURE 語句中 EXTERNAL NAME 子句指定的類名或方法名與實際編譯的 .class 文件不匹配時,會拋出 SQL4304N reason code "1"。
典型錯誤示例: EXTERNAL NAME 'SQL4304RC1!abend' 中類名應為 SQL4304RC1,若寫成 SQL4304RC1(缺少 'L')即會報錯。
修正步驟:
DROP PROCEDURE SQL4304RC1EXTERNAL NAME 拼寫使用 PARAMETER STYLE DB2GENERAL 時,Java 存儲過程類必須繼承 COM.ibm.db2.app.StoredProc。此外,入口方法不能聲明為 public static,必須是實例方法。
錯誤代碼片段:
public class SQL4304RC2 { // 缺少 extends StoredProc
public static void abend(int input) { ... } // 不能是 static
}
正確代碼:
public class SQL4304RC2 extends COM.ibm.db2.app.StoredProc {
public void abend(int input) throws SQLException, Exception { ... }
}
修正後重新編譯、替換 sqllib/function 下的 class 文件即可。
當 EXTERNAL NAME 指定的方法名與 Java 源碼中的方法名大小寫不一致,或參數類型/個數不匹配時觸發。
案例: Java 方法為 public static void iNSERT(String input)(小寫 i),但 EXTERNAL NAME 'INSERT.INSERT' 使用大寫 I。DB2 按 JVM 類型簽名 (Ljava/lang/String;)V 查找方法,發現不匹配。
解決方案: 修正 CREATE PROCEDURE 中的 EXTERNAL NAME 為 'INSERT.iNSERT',或統一 Java 方法名大小寫。
JVM 類型簽名速查表:
| 簽名 | Java 類型 |
|---|---|
| Z | boolean |
| I | int |
| Ljava/lang/String; | String |
| V | void |
| [I | int[] |
詳細規範請參考 JNI 類型簽名文檔。
調用 sqlj.install_jar 時指定的 JAR 文件路徑無效,或文件尚未創建。
修正: 先執行 jar -cvf Out_20200.jar *.class 生成 JAR,再安裝。
sqlj.remove_jar → 需先移除或改用 sqlj.replace_jarsqlj.install_jar 時使用的 ID(如 OUT20200JAR 而非 OUT20200)Java 存儲過程的 EXTERNAL NAME 必須遵循以下格式:
['jar_id':]class_id[.|!]method_id
jar_id:可選,安裝 JAR 時指定的 IDclass_id:Java 類名method_id:方法名:,類與方法之間用 . 或 !常見錯誤:
EXTERNAL NAME 'OUT_LANGUAGE:Out_Language!outLanguage' 中 JAR ID 應為 OUTLANGUAGEJAR(安裝時指定),而非 OUT_LANGUAGEEXTERNAL NAME 'Out_Language:outLanguage' 用 : 分隔類與方法 → 應改為 Out_Language!outLanguage 或 Out_Language.outLanguage| Reason Code | 常見成因 | 解決方案 |
|---|---|---|
| RC=4 | Fixpack 升級後未更新資料庫/實例 | 執行 db2updv8(資料庫)與 db2iupdt(實例) |
| RC=9 | Java 堆/查詢堆/ASL 堆不足 | 調整 java_heap_sz、query_heap_sz、aslheapsz;通常增大前二者、減小後者 |
兩大原因:
CREATE PROCEDURE 定義過程 → 補齊 DDL?,INOUT 參數同輸入示例: OUT_LANGUAGE 需 1 個 OUT 參數 → CALL out_language(?);ALL_DATA_TYPES 需 5 個 INOUT + 5 個 OUT → CALL all_data_types(32000, ..., ?, ?, ?, ?, ?)
db2diag.log 顯示 EACCES (13) 無法訪問 /home/user/sqllib/function/jar/INSTANCE 目錄。
修正: chmod +rw sqllib/function/jar 恢復默認權限。
日誌提示 Insufficient memory available for IPC communication,建議調整 DB2_FMP_COMM_HEAPSZ。
排查順序:
ASLHEAPSZ(默認 15)與 QUERY_HEAP_SZ(默認 1000)是否過大/過小ASLHEAPSZ 過大(如 20000)導致內存耗盡 → 降至 2000DB2_FMP_COMM_HEAPSZ 是否被誤設為 0(會禁用所有 fenced routine) → 刪除該註冊表變量恢復默認常見原因:JVM 被代碼主動終止(如調用 System.exit(0))、堆大小不足、或代碼邏輯導致崩潰。
診斷: 查看 db2diag.log 中的堆棧跟蹤。
典型錯誤代碼:
// 第 23 行導致 JVM 退出
java.lang.Runtime.getRuntime().exit(0);
修正: 移除該行,重新編譯部署。