简体   繁体   English

创建与Oracle数据库的连接时出现java.lang.ArrayIndexOutOfBoundsException

[英]java.lang.ArrayIndexOutOfBoundsException when creating a connection to an Oracle database

It appears that Oracle's java client has a bug - if the tnsnames.ora file has misplaced spaces/tabs/new-lines in particular places, you get an exception with the following trace: 看来Oracle的java客户端有一个错误 - 如果tnsnames.ora文件在特定位置放错了空格/制表符/换行符,则会出现以下跟踪异常:

java.lang.ArrayIndexOutOfBoundsException: <some number>
        at oracle.net.nl.NVTokens.parseTokens(Unknown Source)
        at oracle.net.nl.NVFactory.createNVPair(Unknown Source)
        at oracle.net.nl.NLParamParser.addNLPListElement(Unknown Source)
        at oracle.net.nl.NLParamParser.initializeNlpa(Unknown Source)
        at oracle.net.nl.NLParamParser.<init>(Unknown Source)
        at oracle.net.resolver.TNSNamesNamingAdapter.loadFile(Unknown Source)
        at oracle.net.resolver.TNSNamesNamingAdapter.checkAndReload(Unknown Source)
        at oracle.net.resolver.TNSNamesNamingAdapter.resolve(Unknown Source)
        at oracle.net.resolver.NameResolver.resolveName(Unknown Source)
        at oracle.net.resolver.AddrResolution.resolveAndExecute(Unknown Source)
        at oracle.net.ns.NSProtocol.establishConnection(Unknown Source)
        at oracle.net.ns.NSProtocol.connect(Unknown Source)
        at oracle.jdbc.driver.T4CConnection.connect(T4CConnection.java:1037)
        at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:282)
        at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:468)
        at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:165)
        at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:35)
        at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:839)
        at java.sql.DriverManager.getConnection(DriverManager.java:582)
        at java.sql.DriverManager.getConnection(DriverManager.java:185)

If you take a C++ application and try to connect with it to the database with the same tnsnames.ora in use - it works fine. 如果您使用C ++应用程序并尝试使用相同的tnsnames.ora将其连接到数据库 - 它可以正常工作。 Same goes for sqlplus . sqlplus Also tnsping which should parse this file has no problem resolving any service name. 此外tnsping这应该解析这个文件没有问题,解决任何服务名称。 Seems like Oracle were too lazy to .trim() the values or something - and it is the same problem with Oracle client versions 9, 10 and 11. 似乎Oracle太懒了.trim()值或什么 - 而且Oracle客户端版本9,10和11也是同样的问题。

Any idea why this problem exists and what is the exact problem with the tnsnames.ora format? 知道为什么会出现这个问题以及tnsnames.ora格式的确切问题是什么? (I just remove all white-spaces to resolve it) (我只是删除所有空格来解决它)

I tried the advice from GriffeyDog but unfortunately it did not solve the problem - so eventually I too the check for your self approach : 我尝试了GriffeyDog的建议,但不幸的是它没有解决问题 - 所以最终我也check for your self approach

Oracle's documentation states that the structure of a record in the tnsnames.ora file should be as such: Oracle的文档声明tnsnames.ora文件中记录的结构应该是这样的:

net_service_name= 
 (DESCRIPTION=
   (ADDRESS=...)
   (ADDRESS=...)
   (CONNECT_DATA=
    (SERVICE_NAME=sales.us.example.com)))

Ours was: 我们是:

net_service_name= 
(DESCRIPTION=
(ADDRESS=...)
(ADDRESS=...)
(CONNECT_DATA=
(SERVICE_NAME=sales.us.example.com)))

Apparently the indentation is crucial - if any of the lines in the block of a single net_service_name start at index 1 - this exception is thrown. 显然缩进是至关重要的 - 如果单个net_service_name的块中的任何行从索引1开始 - 抛出此异常。

Only once you add indentation to all (can be spaces or tab) - it works. 只有向所有人添加缩进(可以是空格或制表符) - 它才有效。 It doesn't have to look good, but has to have an offset of some sort. 它不一定好看,但必须有某种偏移。

Important note - the only problem is with '(' , indentation rules don't apply to ')' . 重要提示 - 唯一的问题是'(' ,缩进规则不适用于')'
Eg the below example is perfectly fine: 例如,下面的例子非常好:

net_service_name= 
     (DESCRIPTION=
       (ADDRESS=...
)
       (ADDRESS=...
)
       (CONNECT_DATA=
        (SERVICE_NAME=sales.us.example.com))
)

After searching for this issue to be documented - I finally found out that indeed it is documented at http://download.oracle.com/docs/cd/A57673_01/DOC/net/doc/NWUS233/apb.htm 在搜索了这个需要记录的问题之后 - 我终于发现它确实记录在http://download.oracle.com/docs/cd/A57673_01/DOC/net/doc/NWUS233/apb.htm

And here is the important excerpt: 这是重要的摘录:

Even if you do not choose to indent your files in this way, you must indent a wrapped line by at least one space, or it will be misread as a new parameter . 即使您不选择以这种方式缩进文件,也必须至少用一个空格缩进包装行,否则它将被误读为新参数 The following layout is acceptable: 以下布局是可以接受的:

(ADDRESS=(COMMUNITY=tcpcom.world)(PROTOCOL=tcp) (ADDRESS =(社区= tcpcom.world)(PROTOCOL = TCP)
(HOST=max.world)(PORT=1521)) (HOST = max.world)(PORT = 1521))

The following layout is not acceptable: 以下布局是不可接受的:

(ADDRESS=(COMMUNITY=tcpcom.world)(PROTOCOL=tcp) (ADDRESS =(社区= tcpcom.world)(PROTOCOL = TCP)
(HOST=max.world)(PORT=1521)) (HOST = max.world)(PORT = 1521))

I've seen similar issues arise when a text file is saved with Unix-style end-of-lines (LF) versus DOS/Windows-style (CR/LF), or vice-versa. 我发现当使用Unix风格的行尾(LF)与DOS / Windows风格(CR / LF)保存文本文件时会出现类似的问题,反之亦然。 You might try opening your tnsnames.ora file with an editor that supports saving in both formats to see if you can correct the problem that way. 您可以尝试使用支持以两种格式保存的编辑器打开您的tnsnames.ora文件,以查看是否可以通过这种方式纠正问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM