我遇到了一个非常奇怪的问题 这是JDBC连接到Oracle数据库的非常简单的使用
OS: Ubuntu
Java Version: 1.5.0_16-b02
1.6.0_17-b04
Database: Oracle 11g Release 11.1.0.6.0
当我使用jar文件时
OJDBC14.jar
每次都连接到数据库
当我使用jar文件时
OJDBC5.jar
它连接了一些时间,有时会抛出错误(如下所示)
如果我使用Java 6重新编译并使用
OJDBC6.jar
我得到与OJDBC5.jar
我需要JODB5.jar中的特定功能,这些功能在OJDBC14.jar中不可用
任何想法
错误
> Connecting to oracle
java.sql.SQLException: Io exception: Connection reset
at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:74)
at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:110)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:171)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:227)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:494)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:411)
at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:490)
at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:202)
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:33)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:474)
at java.sql.DriverManager.getConnection(DriverManager.java:525)
at java.sql.DriverManager.getConnection(DriverManager.java:171)
at TestConnect.main(TestConnect.java:13)
代码
以下是我正在使用的代码
import java.io.*;
import java.sql.*;
public class TestConnect {
public static void main(String[] args) {
try {
System.out.println("Connecting to oracle");
Connection con=null;
Class.forName("oracle.jdbc.driver.OracleDriver");
con=DriverManager.getConnection(
"jdbc:oracle:thin:@172.16.48.100:1535:sample",
"JOHN",
"90009000");
System.out.println("Connected to oracle");
con.close();
System.out.println("Goodbye");
} catch(Exception e) { e.printStackTrace(); }
}
}
答案 0 :(得分:90)
在某些OTN论坛(https://kr.forums.oracle.com/forums/thread.jspa?messageID=3699989)中提供了解决此问题的解决方案。但是,没有解释问题的根本原因。以下是我试图解释问题的根本原因。
Oracle JDBC驱动程序以安全的方式与Oracle服务器通信。驱动程序使用 java.security.SecureRandom 类来收集用于保护通信的熵。该类依赖于本机平台支持来收集熵。
熵是由操作系统或应用程序收集/生成的随机性,用于加密或需要随机数据的其他用途。这种随机性通常是从硬件噪声源,硬件噪声,音频数据,鼠标移动或专门提供的随机性生成器中收集的。内核收集熵并存储它是一个熵池,并通过特殊文件 / dev / random 和<使操作系统进程或应用程序可以使用随机字符数据强> 的/ dev / urandom的 即可。
从 / dev / random 读取会消耗具有所请求的位/字节数的熵池,从而提供加密操作中经常需要的高度随机性。如果熵池完全耗尽并且没有足够的熵,则 / dev / random 上的读取操作将阻塞,直到收集到额外的熵。因此,从 / dev / random 读取的应用程序可能会阻塞一段随机时间。
与上述相反,从 / dev / urandom 读取不会阻止。从 / dev / urandom 读取也会消耗熵池,但是当缺少足够的熵时,它不会阻塞,而是重用部分读取的随机数据中的位。据说这很容易受到密码分析攻击。这是一种理论上的可能性,因此不鼓励从 / dev / urandom 中读取以加密加密操作中的随机性。
默认情况下, java.security.SecureRandom 类从 / dev / random 文件读取,因此有时会阻塞随机时间段。现在,如果读取操作没有返回所需的时间,则Oracle服务器会超时客户端(在本例中为jdbc驱动程序)并通过从其末端关闭套接字来中断通信。从阻塞调用返回后尝试恢复通信的客户端遇到IO异常。这个问题可能在任何平台上随机发生,尤其是从硬件噪声中收集熵的情况。
正如OTN论坛所述,此问题的解决方案是覆盖 java.security.SecureRandom 类的默认行为,以使用来自 / dev / urandom的非阻塞读取而不是 / dev / random 的阻塞读取。这可以通过将以下系统属性 -Djava.security.egd = file:/// dev / urandom 添加到JVM来完成。虽然这对于像JDBC驱动程序这样的应用程序来说是一个很好的解决方案,但对于执行密码密钥生成等核心加密操作的应用程序来说,这是不鼓励的。
其他解决方案可能是使用可用于平台的不同随机播种器实现,这些实现不依赖于硬件噪声来收集熵。有了这个,您可能仍需要覆盖 java.security.SecureRandom 的默认行为。
在Oracle服务器端增加套接字超时也可以是一种解决方案,但在尝试此操作之前,应从服务器的角度评估副作用。
答案 1 :(得分:17)
我遇到了完全相同的问题。使用Windows Vista我无法重现问题,但在Ubuntu上我不断重现'连接重置' - 错误。
我找到了 http://forums.oracle.com/forums/thread.jspa?threadID=941911&tstart=0&messageID=3793101该论坛上的用户说:
我用Oracle开了一张票,这就是他们告诉我的。
java.security.SecureRandom是sun提供的标准API。其中 这个类提供的各种方法void nextBytes(byte [])是一个。 该方法用于生成随机字节。 Oracle 11g JDBC 驱动程序使用此API在登录期间生成随机数。用户 使用Linux遇到了SQLException(“Io exception: 连接重置“)。
问题是双重的
当SecureRandom.nextBytes(byte [])时,JVM会尝试列出/ tmp(或-Djava.io.tmpdir设置的备用tmp目录)中的所有文件 被调用。如果文件数量很大,则该方法需要很长时间 时间响应并因此导致服务器超时
- 醇>
方法void nextBytes(byte [])在Linux和某些缺少随机数生成硬件的机器上使用/ dev / random 操作速度降低到整个登录过程的程度 停了下来。最终用户遇到SQLException(“Io 异常:连接重置“)
如果是底层操作系统,升级到11g的用户可能会遇到此问题 Linux是在故障硬件上运行的。
原因尚未确切地确定原因。它可能 要么是硬件问题,要么是出于某种原因 该软件无法从dev / random
读取解决方案更改应用程序的设置,然后添加下一个 java命令的参数:
-Djava.security.egd =文件是:/ dev /../开发/ urandom的
我们在java.security文件中进行了此更改,但它已被删除 错误。
解决了我的问题。
答案 2 :(得分:6)
“连接重置”错误消息通常意味着在尝试创建连接(握手)期间,另一方已中止连接。这有很多可能的原因。 JDBC驱动程序中的错误,数据库端超时,数据库重启,数据库可用连接不足,网络质量差,病毒扫描程序/防火墙/代理程序错误等等。
由于间歇性发生,JDBC驱动程序中的错误可能会被排除在外或更少。留下剩下的可能原因。我建议首先查看数据库服务器的日志。
答案 3 :(得分:2)
很难说,但如果我要检查JDBC驱动程序的实际版本。确保它是11.1.0.6。
Oracle不在文件名中包含数据库版本。所以11.2的驱动程序与11.1 - ojdbc5.jar的驱动程序完全相同。我将解压缩驱动程序jar文件,并找到MANIFEST.MF文件,这将包含一些版本信息。确保JDBC驱动程序的版本与数据库的版本匹配。我怀疑这可能是版本问题,因为Oracle 11.1.0.6 download页面上没有名为ojdbc14.jar的jar文件。
如果版本匹配 - 我没有想法:)
答案 4 :(得分:2)
导致我出现此问题的其他因素是 HOSTNAME 设置错误。我的连接尝试被绞死:
"main" prio=10 tid=0x00007f7cc8009000 nid=0x2f3a runnable [0x00007f7cce69e000]
java.lang.Thread.State: RUNNABLE
at java.net.Inet4AddressImpl.getLocalHostName(Native Method)
at java.net.InetAddress.getLocalHost(InetAddress.java:1444)
at sun.security.provider.SeedGenerator$1.run(SeedGenerator.java:176)
at sun.security.provider.SeedGenerator$1.run(SeedGenerator.java:162)
at java.security.AccessController.doPrivileged(Native Method)
因此,请确保您在/etc/hosts/
中有一个主机名条目。
如果你发出这样的hostname
命令:
$ hostname
my.server.com
您需要/etc/hosts
中的一行:
127.0.0.1 my my.server.com
答案 5 :(得分:1)
我发现这个链接与64位系统,驱动程序jdbc 11g和连接重置相同的问题: http://forums.oracle.com/forums/thread.jspa?messageID=3793101
答案 6 :(得分:1)
只是为了澄清 - 至少从我们在我们身边找到的东西来说明! 在JDK发行版中设置Linux随机化程序是一个问题 - 我们在Java6中发现它,不确定Java7。 随机化器的linux语法是file:/// dev / urandom,但文件中的条目(可能是从Windows保留/复制)作为文件:/ dev / urandom。 那么Java可能会回落到默认值,恰好是/ dev / random。这对无头机器无效!
答案 7 :(得分:1)
此问题的根本原因与用户身份验证版本有关。对于每个数据库用户,多个密码验证程序保留在数据库中。通常,当您升级数据库时,新的密码验证程序将添加到列表中,这是一个更强大的密码验证程序。以下查询显示可供每个用户使用的密码验证程序版本。例如:
SQL> SELECT PASSWORD_VERSIONS FROM DBA_USERS WHERE USERNAME='SCOTT';
PASSWORD_VERSIONS
-----------------
11G 12C
升级到较新的驱动程序时,您可以使用较新版本的验证程序,因为驱动程序和服务器会协商最强的验证程序以供使用。这个更新版本的验证器将更安全,并且将涉及生成更大的随机数或使用更复杂的散列函数,这可以解释为什么在建立JDBC连接时会看到问题。正如其他使用/dev/urandom
的回复所述,通常可以解决这些问题。您还可以决定降级密码验证程序,并使较新的驱动程序使用您之前的驱动程序使用的旧密码验证程序。例如,如果您想使用10G密码验证程序(仅用于测试目的),首先需要确保它可供您的用户使用。
在服务器上的sqlnet.ora中设置SQLNET.ALLOWED_LOGON_VERSION_SERVER=8
。然后:
SQL> alter user scott identified by "tiger";
User altered.
SQL> SELECT PASSWORD_VERSIONS FROM DBA_USERS WHERE USERNAME='SCOTT';
PASSWORD_VERSIONS
-----------------
10G 11G 12C
然后,您可以通过设置此JDBC属性oracle.jdbc.thinLogonCapability="o3"
来强制JDBC瘦驱动程序使用10G验证程序。如果您遇到错误"ORA-28040: No matching authentication protocol"
,那么这意味着您的服务器不允许使用10G验证程序。如果是这种情况,则需要再次检查配置。
答案 8 :(得分:0)
请注意,使用/ dev / urandom的建议解决方案对我来说第一次起作用,但在此之后总是不起作用。
我公司的DBA切换了'SQL * net banners',无论是否有上述内容,我都会永久修复它。
我不知道'SQL * net banners'是什么,但我希望在这里提供这些信息,如果你有一个DBA,他(你)会知道该怎么做。
答案 9 :(得分:0)
禁用SQL Net Banners保存了我们。
答案 10 :(得分:0)
-Djava.security.egd = file:/ dev /./ urandom应该是对的!不是-Djava.security.egd = file:/ dev /../ dev / urandom或-Djava.security.egd = file:/// dev / urandom
答案 11 :(得分:0)
根据Bug https://bugs.openjdk.java.net/browse/JDK-6202721
Java不会出现 -Djava.security.egd = file:/ dev / urandom
它应该是 -Djava.security.egd = file:/ dev /./ urandom
答案 12 :(得分:0)
从詹金斯执行liquibase时,我遇到了同样的问题。有时,此错误被抛出到输出,而liquibase更改日志根本没有执行。
提供的解决方案:在jenkin的maven项目中,jdk已从jdk8-131更新到任何较新的版本(例如java8-162)。
答案 13 :(得分:-1)
OracleXETNSListener - 如果已禁用此服务,则必须启动该服务。
run -> services.msc
并留意那些服务