• ojdbc6中OraclePreparedStatement的ArrayIndexOutOfBoundsException异常BUG-6396242


    现场信息

    Caused by: java.lang.ArrayIndexOutOfBoundsException: -32203
            at oracle.jdbc.driver.OraclePreparedStatement.setupBindBuffers(OraclePreparedStatement.java:2677)
            at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:9270)
            at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:210)
            at weblogic.jdbc.wrapper.PreparedStatement.executeBatch(PreparedStatement.java:191)
            ... 6 more

    运行时OraclePreparedStatement相关jar加载信息

     

    排查解决

    首先,看到有人遇到类似的问题,主要提到两点问题:

    第一点,Ojdbc.jar和Oracle的版本有一个匹配关系的,对应关系如下图:

    Oracle 版本JDK版本推荐jar包
    Oracle 10g JDK 1.4 and 1.5 ojdbc14.jar
    Oracle 11g JDK1.5 ojdbc5.jar
    Oracle 11g JDK1.6 ojdbc6.jar

    第二点:Ojdbc14版本在进行executeBatch操作的时候,如果参数多于32766会出现越界问题。

     

    但是我的Ojdbc6.jar版本是:

    Manifest-Version: 1.0
    Implementation-Vendor: Oracle Corporation
    Implementation-Title: ojdbc6.jar
    Implementation-Version: Oracle JDBC Driver version - "11.1.0.6.0-Production+"
    Implementation-Time: Tue Oct 30 03:33:58 2007
    Specification-Vendor: Oracle Corporation
    Created-By: 1.6.0 (Sun Microsystems Inc.)
    Specification-Title: Oracle JDBC driver classes for use with JDK6
    Specification-Version: Oracle JDBC Driver version - "11.1.0.6.0-Production+" 

    Oracle版本

    select * from v$version;
    Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

    所以排除第一点版本匹配方面问题。

    然后,从第二点数据量来看,我实际的批量提交量在56*1000=56000左右,而且已经有1000条记录正常写入,推测不完全是batch数量方面的问题。

    理所当然尝试在开发环境复现问题,但是死活复现不了,怀疑开发和正式环境差异,添加VM参数-XX:+TraceClassLoading观察,发现tomcat加载的Ojdbc版本是ojdbc14,尽管ojdbc14没有问题,但目前看来这个还和中间件类加载顺序或者机制有关,并且肯定不能轻易的拿tomcat的ojdbc14去替换weblogic默认的ojdbc6。

    测试环境将ojdbc14强行删掉只留ojdbc6后,终于复现了问题,与此同时如果把批量从1000降到500问题便消失,然后升到550问题重新出现(但是这时提交量在56*550=30800明显低于32768);再次说明不完全是batch数量的问题,从现象来看是在参数个数和行数达到某些条件同时批量到达一定长度后,多次提交才会触发此问题。

    解决方法

    1降低批量提交数量;2升级ojdbc6的版本。两种不同的解决方案,1并不是长久之计,还是要从根本上解决问题。

    现在唯一能确定的就是ojdbc6出了问题,掉回头来搜索具体版本号:11.1.0.6.0,果然在11.1.0.7.0官方文档中找到了个修复相关bug的列表,

     

    下载11.1.0.7.0新版的ojdbc6之后问题解决

    原因分析

    反编译后对比新旧两个版本的ojdbc6,定位到错误抛出方法setupBindBuffers,发现其中只有一行代码发生变动

     但是由于反编译的代码隐去了很多具体意义变量,这里只能初步判断就是此处附近取值时发生了数组越界异常; 

    思考总结

    这里对模拟线上环境使用了arthas进行了类加载定位,但是对于没有安装arthas的环境,如何才能获取到jar具体的加载信息这个需要进一步了解jvm相关tools。

    排查过程中开发测试环境前期始终不能复现bug这个问题应该在发布、测试中引起注意,中间件的差异点要有预期。中间件的类加载器、加载机制相关内容需要进一步了解。

  • 相关阅读:
    Java_适配器模式
    linux常用命令整理
    (转)使用隐藏的iframe 隐藏form提交,仿AJax无刷新提交,可以实现无刷新上传文件
    mysql添加并返回主键
    学习RMI
    关于bcprov-jdk16
    JavaScript在页面中的引用方法
    通过CFX发布WebService(一)
    字符串和json数据的转换
    MD5 加密与解密
  • 原文地址:https://www.cnblogs.com/elfcafe/p/12974826.html
Copyright © 2020-2023  润新知