Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the Java 7 try-with-resources bytecode equivalent using try-catch-finally?

Tags:

I'm trying to understand how the new try-with-resources statement works by recreating it using regular try-catch-finally statements. Given the following test class using Java 7 try-with-resources:

import java.io.IOException; import java.util.zip.GZIPOutputStream;  public class TryWithResources {     public static void main(String[] args) {         try (GZIPOutputStream gzip = new GZIPOutputStream(System.out)) {             gzip.write("TEST".getBytes("UTF-8"));         } catch (IOException ioe) {             ioe.printStackTrace();         }     } } 

How would you rewrite this class to use try-catch-finally statements which produces exactly the same bytecode as the try-with-resources statement produces? Also, same question when two resources are used, as in the following example:

import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.zip.GZIPOutputStream;  public class TryWithResources2 {     public static void main(String[] args) {         try (ByteArrayOutputStream baos = new ByteArrayOutputStream();                 GZIPOutputStream gzip = new GZIPOutputStream(baos)) {             gzip.write("TEST".getBytes("UTF-8"));         } catch (IOException ioe) {             ioe.printStackTrace();         }     } } 
like image 364
Dan Cruz Avatar asked Oct 22 '11 14:10

Dan Cruz


People also ask

Does try with resources need catch or finally?

A try-with-resources statement can have catch and finally blocks just like an ordinary try statement.

Can we use finally with try with resources in Java?

Note: A try -with-resources statement can have catch and finally blocks just like an ordinary try statement. In a try -with-resources statement, any catch or finally block is run after the resources declared have been closed.

What is the try with resources statement in Java?

The try-with-resources statement ensures that each resource is closed at the end of the statement execution. If we don't close the resources, it may constitute a resource leak and also the program could exhaust the resources available to it. You can pass any object as a resource that implements java.

Which one of the option is valid to close the resources automatically in Java 7?

automatic resource management or try-with-resources is a new exception handling mechanism that was introduced in Java 7, which automatically closes the resources used within the try-catch block.


2 Answers

For the TryWithResources class, the following class produces equivalent bytecode as the try-with-resources:

import java.io.IOException; import java.util.zip.GZIPOutputStream;  public class TryCatchFinally {     public static void main(String[] args) {         try {             final GZIPOutputStream gzip = new GZIPOutputStream(System.out);             Throwable gzipEx = null;             try {                 gzip.write("TEST".getBytes("UTF-8"));             } catch (Throwable t) {                 gzipEx = t;                 throw t;             } finally {                 if (gzip != null) {                     if (gzipEx != null) {                         try {                             gzip.close();                         } catch (Throwable t) {                             gzipEx.addSuppressed(t);                         }                     } else {                         gzip.close();                     }                 }             }         } catch (IOException ioe) {             ioe.printStackTrace();         }     } } 

Using Sun JDK 1.7.0, the bytecode and exception tables for the main method in both TryWithResources and TryCatchFinally classes is:

  stack=3, locals=6, args_size=1      0: new           #2                  // class java/util/zip/GZIPOutputStream      3: dup                 4: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;      7: invokespecial #4                  // Method java/util/zip/GZIPOutputStream."<init>":(Ljava/io/OutputStream;)V     10: astore_1           11: aconst_null        12: astore_2           13: aload_1            14: ldc           #5                  // String TEST     16: ldc           #6                  // String UTF-8     18: invokevirtual #7                  // Method java/lang/String.getBytes:(Ljava/lang/String;)[B     21: invokevirtual #8                  // Method java/util/zip/GZIPOutputStream.write:([B)V     24: aload_1            25: ifnull        95     28: aload_2            29: ifnull        48     32: aload_1            33: invokevirtual #9                  // Method java/util/zip/GZIPOutputStream.close:()V     36: goto          95     39: astore_3           40: aload_2            41: aload_3            42: invokevirtual #11                 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V     45: goto          95     48: aload_1            49: invokevirtual #9                  // Method java/util/zip/GZIPOutputStream.close:()V     52: goto          95     55: astore_3           56: aload_3            57: astore_2           58: aload_3            59: athrow             60: astore        4     62: aload_1            63: ifnull        92     66: aload_2            67: ifnull        88     70: aload_1            71: invokevirtual #9                  // Method java/util/zip/GZIPOutputStream.close:()V     74: goto          92     77: astore        5     79: aload_2            80: aload         5     82: invokevirtual #11                 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V     85: goto          92     88: aload_1            89: invokevirtual #9                  // Method java/util/zip/GZIPOutputStream.close:()V     92: aload         4     94: athrow             95: goto          103     98: astore_1           99: aload_1           100: invokevirtual #13                 // Method java/io/IOException.printStackTrace:()V    103: return           Exception table:      from    to  target type         32    36    39   Class java/lang/Throwable         13    24    55   Class java/lang/Throwable         13    24    60   any         70    74    77   Class java/lang/Throwable         55    62    60   any          0    95    98   Class java/io/IOException 

For the TryWithResources2 class, the following class produces equivalent bytecode as the try-with-resources:

import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.zip.GZIPOutputStream;  public class TryCatchFinally2 {     public static void main(String[] args) {         try {             final ByteArrayOutputStream baos = new ByteArrayOutputStream();             Throwable baosEx = null;             try {                 final GZIPOutputStream gzip = new GZIPOutputStream(baos);                 Throwable gzipEx = null;                 try {                     gzip.write("TEST".getBytes("UTF-8"));                 } catch (Throwable t) {                     gzipEx = t;                     throw t;                 } finally {                     if (gzip != null) {                         if (gzipEx != null) {                             try {                                 gzip.close();                             } catch (Throwable t) {                                 gzipEx.addSuppressed(t);                             }                         } else {                             gzip.close();                         }                     }                 }             } catch (Throwable t) {                 baosEx = t;                 throw t;             } finally {                 if (baos != null) {                     if (baosEx != null) {                         try {                             baos.close();                         } catch (Throwable t) {                             baosEx.addSuppressed(t);                         }                     } else {                         baos.close();                     }                 }             }         } catch (IOException ioe) {             ioe.printStackTrace();         }     } } 

The bytecode and exception tables for the main method in both TryWithResources2 and TryCatchFinally2 classes is:

  stack=3, locals=10, args_size=1      0: new           #2                  // class java/io/ByteArrayOutputStream      3: dup                 4: invokespecial #3                  // Method java/io/ByteArrayOutputStream."<init>":()V      7: astore_1            8: aconst_null         9: astore_2           10: new           #4                  // class java/util/zip/GZIPOutputStream     13: dup                14: aload_1            15: invokespecial #5                  // Method java/util/zip/GZIPOutputStream."<init>":(Ljava/io/OutputStream;)V     18: astore_3           19: aconst_null        20: astore        4     22: aload_3            23: ldc           #6                  // String TEST     25: ldc           #7                  // String UTF-8     27: invokevirtual #8                  // Method java/lang/String.getBytes:(Ljava/lang/String;)[B     30: invokevirtual #9                  // Method java/util/zip/GZIPOutputStream.write:([B)V     33: aload_3            34: ifnull        114     37: aload         4     39: ifnull        61     42: aload_3            43: invokevirtual #10                 // Method java/util/zip/GZIPOutputStream.close:()V     46: goto          114     49: astore        5     51: aload         4     53: aload         5     55: invokevirtual #12                 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V     58: goto          114     61: aload_3            62: invokevirtual #10                 // Method java/util/zip/GZIPOutputStream.close:()V     65: goto          114     68: astore        5     70: aload         5     72: astore        4     74: aload         5     76: athrow             77: astore        6     79: aload_3            80: ifnull        111     83: aload         4     85: ifnull        107     88: aload_3            89: invokevirtual #10                 // Method java/util/zip/GZIPOutputStream.close:()V     92: goto          111     95: astore        7     97: aload         4     99: aload         7    101: invokevirtual #12                 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V    104: goto          111    107: aload_3           108: invokevirtual #10                 // Method java/util/zip/GZIPOutputStream.close:()V    111: aload         6    113: athrow            114: aload_1           115: ifnull        185    118: aload_2           119: ifnull        138    122: aload_1           123: invokevirtual #13                 // Method java/io/ByteArrayOutputStream.close:()V    126: goto          185    129: astore_3          130: aload_2           131: aload_3           132: invokevirtual #12                 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V    135: goto          185    138: aload_1           139: invokevirtual #13                 // Method java/io/ByteArrayOutputStream.close:()V    142: goto          185    145: astore_3          146: aload_3           147: astore_2          148: aload_3           149: athrow            150: astore        8    152: aload_1           153: ifnull        182    156: aload_2           157: ifnull        178    160: aload_1           161: invokevirtual #13                 // Method java/io/ByteArrayOutputStream.close:()V    164: goto          182    167: astore        9    169: aload_2           170: aload         9    172: invokevirtual #12                 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V    175: goto          182    178: aload_1           179: invokevirtual #13                 // Method java/io/ByteArrayOutputStream.close:()V    182: aload         8    184: athrow            185: goto          193    188: astore_1          189: aload_1           190: invokevirtual #15                 // Method java/io/IOException.printStackTrace:()V    193: return           Exception table:      from    to  target type         42    46    49   Class java/lang/Throwable         22    33    68   Class java/lang/Throwable         22    33    77   any         88    92    95   Class java/lang/Throwable         68    79    77   any        122   126   129   Class java/lang/Throwable         10   114   145   Class java/lang/Throwable         10   114   150   any        160   164   167   Class java/lang/Throwable        145   152   150   any          0   185   188   Class java/io/IOException 
like image 101
Dan Cruz Avatar answered Oct 13 '22 12:10

Dan Cruz


According to section 14.20.3.1 of the Java Language Specification (JLS) for Java 7:

try (VariableModifiersopt R Identifier = Expression ...)     Block 

is equivalent to

{     final VariableModifiers_minus_final R Identifier = Expression;     Throwable #primaryExc = null;     try ResourceSpecification_tail         Block     catch (Throwable #t) {         #primaryExc = #t;         throw #t;     } finally {         if (Identifier != null) {             if (#primaryExc != null) {                 try {                     Identifier.close();                 } catch (Throwable #suppressedExc) {                     #primaryExc.addSuppressed(#suppressedExc);                 }             } else {                 Identifier.close();             }         }     } } 

The JLS goes into a lot more detail ... too much to reproduce here.


The Java 7 JLS chapter on try-with-resources is available in HTML form here, and you can get the PDF version of the JLS here.

like image 23
Stephen C Avatar answered Oct 13 '22 12:10

Stephen C