How Java gracefully shuts down the resource try with resource and its abnormal suppression

  • 2021-06-29 10:51:08
  • OfStack

1. Background

We know that in the Java programming process, if external resources (files, database connections, network connections, etc.) are opened, we must manually close them after they have been used.Because external resources are not managed by JVM, we cannot enjoy the JVM garbage collection mechanism. If we do not ensure that external resources are shut down at the right time when programming, it will lead to the leakage of external resources. Then there will be a lot of serious problems, such as abnormal file occupation, excessive database connections, connection pool overflow, and so on.

2. Traditional ways of closing resources

To ensure that External Resource 1 must be shut down, the shutdown code is usually written in the finally code block. Of course, we must also be aware of exceptions that may be thrown when the resource is shut down, so we have the following classic code:


public static void main(String[] args) {
  FileInputStream inputStream = null;
  try {
    inputStream = new FileInputStream(new File("test"));
    System.out.println(inputStream.read());
  } catch (IOException e) {
    throw new RuntimeException(e.getMessage(), e);
  } finally {
    if (inputStream != null) {
      try {
        inputStream.close();
      } catch (IOException e) {
        throw new RuntimeException(e.getMessage(), e);
      }
    }
  }
}

Friends familiar with other languages may start to spit. In C+, we can put the code that closes the resource in the destructor. In C#, we have the using code block.These grammars share a common feature that associates the shutdown behavior of an external resource with the life cycle of the external resource's handle object. When the life cycle of the external resource's handle object ends (for example, when the handle object is out of scope), the shutdown behavior of the external resource is invoked automatically.This not only conforms to the object-oriented programming concept (cohesing the behavior of closing external resources in the handle object of external resources), but also makes the code more concise and understandable.How come Java can't find the syntax feature to automatically shut down external resources.

3. Resource shutdown methods for JDK7 and beyond

3.1 try-with-resource syntax

Indeed, prior to JDK7, Java did not automatically turn off the syntax of external resources until try-with-resource syntax was added to JDK7.

So what is try-with-resource?In short, when an external resource's handle object (such as the FileInputStream object) implements the AutoCloseable interface, the above board code can be simplified as follows:


public static void main(String[] args) {
  try (FileInputStream inputStream = new FileInputStream(new File("test"))) {
    System.out.println(inputStream.read());
  } catch (IOException e) {
    throw new RuntimeException(e.getMessage(), e);
  }
}

Place the creation of the handle object to the external resource in parentheses after the try keyword. When this try-catch code block is executed, Java ensures that the close method of the external resource is called.Is the code much simpler in an instant?

3.2 Implementation Principles

try-with-resource is not a new feature of the JVM virtual machine, but JDK implements a grammatical sugar. When you decompile the code above, you will find that for the JVM virtual machine, it still sees the same writing as before:


public static void main(String[] args) {
  try {
    FileInputStream inputStream = new FileInputStream(new File("test"));
    Throwable var2 = null;

    try {
      System.out.println(inputStream.read());
    } catch (Throwable var12) {
      var2 = var12;
      throw var12;
    } finally {
      if (inputStream != null) {
        if (var2 != null) {
          try {
            inputStream.close();
          } catch (Throwable var11) {
            var2.addSuppressed(var11);
          }
        } else {
          inputStream.close();
        }
      }

    }

  } catch (IOException var14) {
    throw new RuntimeException(var14.getMessage(), var14);
  }
}

3.3 Abnormal Suppression

With decompiled code, you may notice a special handling of exceptions in the code:


var2.addSuppressed(var11);

This is another point of knowledge involved in the try-with-resource syntax, called anomaly suppression.If you encounter exceptions when processing external resources (such as reading or writing) and subsequently encounter exceptions when closing external resources, then catch will encounter exceptions when processing external resources. The exceptions encountered when closing resources will be "suppressed" but not discarded, through the exception getSuppressed method,Suppressed anomalies can be extracted.

4. Summary

1. When an external resource's handle object implements the AutoCloseable interface, JDK7 can use the try-with-resource grammar to more elegantly close resources and eliminate slab code.

2. When try-with-resource, if the processing of external resources and the shutdown of external resources both encounter exceptions, the "shutdown exception" will be suppressed and the "handle exception" will be thrown, but the "shutdown exception" is not lost but stored in the list of suppressed exceptions "handle exception".


Related articles: