【问题标题】:JDBC Lotus-Oracle error: Java.lang.ArrayIndexOutOfBoundsException: Array index out of range: -1JDBC Lotus-Oracle 错误:Java.lang.ArrayIndexOutOfBoundsException:数组索引超出范围:-1
【发布时间】:2017-10-23 21:58:14
【问题描述】:

我正在使用 jdbc 连接到 Oracle 10g 数据库。在 Eclipse/Java 中建立连接工作正常。但是,当我将代码移动到 Lotus 8.5.2 代理时,我最终会遇到以下错误:

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");

我尝试以不同的方式解决这个问题: - 在 Eclipse 中使用 Lotus JVM - 在 Eclipse 中使用不同的 jdbc jar - 使用不同的方式在 Lotus 中建立连接 - 在 lotus 中使用不同的 jdbc jars jars

最后我移动了 ojdbc14.jar 文件 Lotus\Notes\jvm\lib\ext 目录,它现在可以正常工作了。 此解决方案将起作用,但显然我更喜欢将这个 jar 与 nsf 一起分发。有什么办法可以实现吗?

正如leyrer 所建议的那样。我尝试将以下行添加到“/jvm/lib/security/java.policy”文件中

permission java.security.AllPermission;

这确实会导致相同的错误消息。 现在我会坚持将 ojdbc5.jar 放在 /ext 目录中。

【问题讨论】:

  • 只是我好奇您在 LotusNotes 中使用的是哪个 JDBC 驱动程序,LotusDomino,因为据我所知,IBM 长期以来不支持 LotusFamily 的 JDBC 驱动程序
  • ojdbc14.jar 类,用于来自 oracle 站点的 JDK 1.4 和 1.5。我也试过 ojdbc5.jar。
  • 想象一下,不确定代理是否从外部支持 JDBC,从 Domino 方面你可以做到这一点,有趣的是我会标记为通知

标签: java oracle jdbc lotus-notes


【解决方案1】:

如果您使用的是解压后的 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>

【讨论】:

    【解决方案2】:

    我猜想,JVM 的安全管理器不允许访问网络,因为安全策略未指定允许此操作。 详情请见Flying Saucer in Lotus Notes

    【讨论】:

    • 堆栈跟踪让我措手不及。将 jar 放在 ext 目录中证明这与安全性有关。我在另一篇文章中读过你的cmets。但是添加“权限 java.security.AllPermission;”到策略文件没有帮助。
    • 抱歉回复晚了。也许连接字符串是错误的? stackoverflow.com/questions/3573861/…
    【解决方案3】:

    这个问题很久以前就出现了......但是我必须在这个月为一位客户发现它。除了一些虚假的借口和不完整的分析外,我无处找到解决方案。因此,对于遇到它的所有人,我将分享我的发现、问题的根本原因以及解决问题的机会。我已经用驱动程序(ojdbc6.jar)的版本 11.2.0.4 对其进行了测试。此外,如果您的数据库使用 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 默认类加载器),或者您更改类加载过程如下:

    1. 创建一个自定义类加载器: 公共类 CustomLoader 扩展 ClassLoader {

      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();
      }
      
    2. 在多米诺代理中,在任何其他操作发生之前,通过反射改变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";

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-16
      相关资源
      最近更新 更多