JDBC Lotus Oracle错误:Java.lang.ArrayIndexOutOfBoundsException:数组索引超出范围:-1
我正在使用jdbc连接到Oracle 10g数据库。在Eclipse/Java中构建连接工作正常。但是,当我将代码移动到Lotus 8.5.2代理时,我会出现以下错误: 我试图用不同的方法解决这个问题: -在eclipse中使用LotusJVM -在eclipse中使用不同的JDBCJAR -使用不同的方法在Lotus中构建连接 -在lotus中使用不同的jdbc jar 最后,我移动了ojdbc14.jar文件Lotus\Notes\jvm\lib\ext目录,现在可以正常工作了。 这个解决方案会起作用,但显然我更喜欢将这个jar与nsf一起分发。我有什么办法可以做到这一点吗 正如我的建议。我尝试将以下行添加到“/jvm/lib/security/java.policy”文件中 这确实会导致相同的错误消息。JDBC Lotus Oracle错误:Java.lang.ArrayIndexOutOfBoundsException:数组索引超出范围:-1,java,oracle,jdbc,lotus-notes,Java,Oracle,Jdbc,Lotus Notes,我正在使用jdbc连接到Oracle 10g数据库。在Eclipse/Java中构建连接工作正常。但是,当我将代码移动到Lotus 8.5.2代理时,我会出现以下错误: 我试图用不同的方法解决这个问题: -在eclipse中使用LotusJVM -在eclipse中使用不同的JDBCJAR -使用不同的方法在Lotus中构建连接 -在lotus中使用不同的jdbc jar 最后,我移动了ojdbc14.jar文件Lotus\Notes\jvm\lib\ext目录,现在可以正常工作了。 这个解决方
现在,我将坚持将ojdbc5.jar放在/ext目录中。我猜JVM的安全管理器不允许访问网络,因为安全策略没有指定允许此操作。
有关更多详细信息,请参阅。如果您使用的是未打包的ojdbc jar,请确保没有排除oracle/sql/converter\u 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>
org.apache.maven.plugins
maven依赖插件
解包依赖项
准备包装
解包依赖项
聚甲醛
**/*.class,***.glb
${project.build.directory}/classes
假的
真的
很久以前,这个问题就出现了。。。但我必须在这个月为一位客户发现它。除了一些虚假的借口和不完整的分析,我没有找到解决办法。因此,对于你们所有遇到它的人,我将分享我的发现、问题的根本原因以及你们解决问题的机会。我已经用11.2.0.4版的驱动程序(ojdbc6.jar)对其进行了测试。此外,如果您的数据库使用UTF-8编码,它似乎只适用于java.policy调整。在我的例子中,它是一个使用Windows1252编码的数据库
首先,oracle jdbc驱动程序需要进行一些安全性调整。。。最好显式地设置它们,而不是通过permission java.security.AllPermission代码>。使用此权限,从ocacle jdbc驱动程序下载页面(ojdbc.policy文件)获取:
设置到位后,您将遇到Java.lang.ArrayIndexOutOfBoundsException:数组索引超出范围:-1
问题。其根本原因是java代理的类装入器(lotus.domino.AgentLoader)没有实现getResource(字符串名),这导致总是将null
返回给调用方法。由于orcale jdbc驱动程序需要jar中的oracle.sql.converter\u 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();
}
在domino代理中,在执行任何其他操作之前,使用反射更改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”;
我很好奇您在LotusNotes、LotusDomino中使用的JDBC驱动程序,因为我知道IBM long time不支持用于oracle站点JDK 1.4和1.5的LotusFamilyojdbc14.jar类的JDBC驱动程序。我也尝试了ojdbc5.jar,不确定代理是否从外部支持JDBC你可以这样做,有趣的是,我将标记为通知堆栈跟踪,这让我措手不及。将jar放在ext目录中证明这与安全性有关。我在另一篇文章中阅读了你的评论。但是添加了“permission java.security.AllPermission;”对策略文件无效。很抱歉,答复太晚。可能是连接字符串错误?
<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>
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";
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();
}
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));
...