JDBC Lotus-Oracle错误:Java.lang.ArrayIndexOutOfBoundsException:数组索引超出范围:-1
我正在使用jdbc连接到Oracle 10g数据库。在Eclipse/Java中构建连接可以正常工作。然而,当我的代码移动到一个Lotus 8.5.2剂我结束了以下错误(S):JDBC Lotus-Oracle错误:Java.lang.ArrayIndexOutOfBoundsException:数组索引超出范围:-1
Java.lang.ArrayIndexOutOfBoundsException: Array index out of range: -1
at oracle.jdbc.driver.T4CTTIoauthenticate.setSessionFields(T4CTTIoauthenticate.java:1019)
at oracle.jdbc.driver.T4CTTIoauthenticate.<init>(T4CTTIoauthenticate.java:186)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:354)
at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:454)
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:802)
at oracle.jdbc.pool.OracleDataSource.getPhysicalConnection(OracleDataSource.java:298)
at oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.java:222)
at oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.java:166)
at JavaAgent.NotesMain(Unknown Source)
at lotus.domino.AgentBase.runNotes(Unknown Source)
at lotus.domino.NotesThread.run(Unknown Source)
这是用于连接的代码:
Class.forName("oracle.jdbc.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@:xx.xx.xx.xx:1521:xx", "xx", "xx");
我试图以不同的方式解决这个问题: - 使用Lotus JVM在eclipse - 在Eclipse中使用 不同的JDBC罐子 - 用不同的方式来构建在Lotus 连接 - 莲花使用不同的JDBC瓶瓶
最后我移动了ojdbc14.jar文件Lotus \ Notes \ jvm \ lib \ ext目录,现在它工作正常。 这个解决方案可以工作,但显然我更喜欢将这个jar和nsf一起发布。我能做到这一点吗?
如leyrer所示。我尝试添加以下行到“/jvm/lib/security/java.policy”文件
permission java.security.AllPermission;
这并不在相同的错误消息的结果。 现在我会坚持把ojdbc5.jar放在/ ext目录下。
我猜测,JVM的安全管理器不允许访问网络,因为安全策略没有指定允许这个动作。 请参阅Flying Saucer in Lotus Notes了解更多详情。
堆栈跟踪引起了我的错误。将jar放在ext目录中证明这与安全性有关。我已在其他帖子中阅读您的评论。但是添加“权限java.security.AllPermission;”到政策文件没有帮助。 –
对不起,延迟回复。也许连接字符串是错误的? http://stackoverflow.com/questions/3573861/problem-in-connecting-oracle-11g-through-jdbc-thin-driver-domino-java – leyrer
如果您使用解包的ojdbc jar,请确保您不排除oracle/sql/converter_xcharset/*。glb文件。当我的可执行jar使用Maven构建时,我得到了同样的错误,但没有包含这些文件。下面的块明确包含它们。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<excludeTypes>pom</excludeTypes>
<includes>**/*.class,**/*.glb</includes>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
很久以前,这个问题就出现了...但我不得不在本月为客户发现它。我找不到解决办法,但有一些虚假的假设和不完整的分析。因此,对于所有人来说,我会分享我的发现,问题的根源以及解决问题的机会。我使用驱动程序的版本11.2.0.4(ojdbc6.jar)对其进行了测试。此外,如果您的数据库使用UTF-8编码,它似乎只适用于java.policy调整。就我而言,它是一个带有Windows 1252编码的数据库。
首先,oracle jdbc驱动程序需要一些安全性调整......最好是明确地设置它们,而不是permission java.security.AllPermission;
。使用这个权限,从ocacle JDBC驱动程序下载页面(ojdbc.policy文件)采取:
permission java.util.PropertyPermission "user.name", "read";
permission java.util.PropertyPermission "oracle.jdbc.*", "read";
permission java.util.PropertyPermission "oracle.net.wallet_location", "read";
permission java.util.PropertyPermission "oracle.net.tns_admin", "read";
permission javax.management.MBeanServerPermission "createMBeanServer";
permission javax.management.MBeanPermission "oracle.jdbc.driver.OracleDiagnosabilityMBean#[com.oracle.jdbc:type=diagnosability,*]", "registerMBean";
permission javax.management.MBeanTrustPermission "register";
在此之后设置是否正确,你会碰上Java.lang.ArrayIndexOutOfBoundsException: Array index out of range: -1
问题。其根本原因在于,java代理的类加载器(lotus.domino.AgentLoader)没有实现getResource(String name),并且导致始终将null
返回给调用方法。由于orcale jdbc驱动程序需要jar中的oracle.sql.converter_xcharset
文件夹中的glb文件才能正常工作,并且它们由上面提到的getRousource方法加载,所以这不起作用!结果是ArrayIndexOutOfBoundsException。
所以,唯一的解决方案是要么使用从文件系统驱动程序(并使用JVM默认的类加载器),或者修改类加载过程如下:
-
创建自定义的类装载器: 公共类CustomLoader延伸类加载器{
private final AgentLoader loader; public CustomLoader(AgentLoader agentLoader, ClassLoader parent) { super(parent); loader = agentLoader; } @Override public URL getResource(String name) { InputStream is = loader.getResourceAsStream(name); if (is == null) { return super.getResource(name); } try { is.close(); } catch (IOException e) { e.printStackTrace(); return null; } try { URL url = new URL("dominoinmemory", "", -1, name, new DominoInMemoryStreamHandler(name)); System.out.println(url); return url; } catch (MalformedURLException e) { e.printStackTrace(); return null; } } private class DominoInMemoryStreamHandler extends URLStreamHandler { private String resName; byte[] content = null; public DominoInMemoryStreamHandler(String resName) { this.resName = resName; } @Override protected URLConnection openConnection(final URL u) throws IOException { if (!u.getProtocol().equals("dominoinmemory")) throw new IOException("Cannot handle protocol: " + u.getProtocol()); InputStream is = loader.getResourceAsStream(resName); content = toByteArray(is); return new URLConnection(u) { @Override public int getContentLength() { if (content != null) { return content.length; } else { return super.getContentLength(); } } @Override public void connect() throws IOException { if (content != null) { connected = true; } else { throw new IOException("The resource '" + resName + "' was not found"); } } @Override public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(content); } }; } } public static byte[] toByteArray(InputStream input) throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(); byte[] buffer = new byte[4096]; long count = 0; int n = 0; while (-1 != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } return output.toByteArray(); }
-
在多米诺剂,发生任何其它操作之前,用反射
改变AgentLoader的父类加载器public void NotesMain() { try { AgentLoader agentLoader = (AgentLoader) getClass().getClassLoader(); Field f1 = agentLoader.getClass().getSuperclass().getDeclaredField("parent"); f1.setAccessible(true); ClassLoader parent = (ClassLoader) f1.get(agentLoader); f1.set(agentLoader, new CustomLoader(agentLoader, parent)); ...
注意:
- 使用此风险自负!
- 此代码需要在政策文件中的两个附加条目:
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
permission java.net.NetPermission "specifyStreamHandler";
只是我的好奇心JDBC驱动程序使用的是这对LotusNotes,LotusDomino,因为我知道, IBM长时间不支持用于LotusFamily的JDBC驱动程序 – mKorbel
ojdbc14.jar类与Oracle站点中的JDK 1.4和1.5一起使用。我也尝试了ojdbc5.jar。 –
成像,不知道是否代理支持来自外部的JDBC,从Domino方面你可以做到这一点,有趣的我会标记为通知 – mKorbel