others-How to solve connection reset exception when connecting with Oracle 11g with JDBC

1. The purpose of this post

Sometimes, when we execute sql via JDBC with Oracle , we get this exception or error like this:

> java -jar myapp.jar
> IO exception: connection reset

2. Solution

According to this post,there are two possible reasons you get this error:

java.security.SecureRandom is a standard API provided by sun. Among various methods offered by this class void nextBytes(byte[]) is one. This method is used for generating random bytes. Oracle 11g JDBC drivers use this API to generate random number during login. Users using Linux have been encountering SQLException(“Io exception: Connection reset”).

  1. The JVM tries to list all the files in the /tmp (or alternate tmp directory set by -Djava.io.tmpdir) when SecureRandom.nextBytes(byte[]) is invoked. If the number of files is large the method takes a long time to respond and hence cause the server to timeout
  1. The method void nextBytes(byte[]) uses /dev/random on Linux and on some machines which lack the random number generating hardware the operation slows down to the extent of bringing the whole login process to a halt. Ultimately the the user encounters SQLException(“Io exception:Connection reset”)

You can resolve the issue by adding this option to your command or system property:

2.1 Solution 1

-Djava.security.egd=file:/dev/../dev/urandom

But what is java.security.egd?

SecureRandom is widely used in various Java components and can reliably generate random numbers. However, in scenarios where a large number of random numbers are generated, the performance will be low. In this case, you can use “-Djava.security.egd=file:/dev/./urandom” to speed up the random number generation process.

Taking the use of nextBytes to generate random numbers when generating uuid as the entry point, let’s take a look at the code logic of SecureRandom.

   public static UUID randomUUID() {
        SecureRandom ng =Holder.numberGenerator;
        byte[] randomBytes = new byte[16];
        ng.nextBytes(randomBytes);
        randomBytes[6] &= 0x0f;  /* clear version       */
        randomBytes[6]  |=0x40;  /* set to version 4     */
        randomBytes[8] &= 0x3f;  /* clear variant       */
        randomBytes[8]  |=0x80;  /* set to IETF variant  */
        return newUUID(randomBytes);
    }

Through testing, we can find that hotspot needs to use the configuration item “- Djava.security.egd=file:/dev/./urandom” to read data from urandom. Here openjdk has made an optimization to read data directly from urandom.

/dev/random is slower than /dev/urandom when generating a large number of random numbers. Therefore, it is recommended to specify the random number generator as /dev/./urandom when using a large number of random numbers.

Configuring -Djava.security.egd=file:/dev/./urandom when starting the application can speed up application startup to a certain extent.

2.2 Solution 2

System.setProperty("java.security.egd", "file:///dev/urandom");  // the 3 '/' are important to make it an URL

2.3 My solution

I choose the first solution:

> java -jar myapp.jar -Djava.security.egd=file:/dev/../dev/urandom

Run the command again , everything works fine now.