使用try-catch-finally等效于Java 7 try-with-resources字节码是什么?

发布于 2021-01-30 17:59:05

我试图通过使用常规try-catch-finally语句重新创建新的try-with-
resources语句
来了解其工作方式。给定以下使用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();
        }
    }
}

您将如何重写此类以使用try-catch-finally语句,该语句所产生的字节码与try-with-
resources语句所产生的字节码完全相同?同样,当使用两个资源时,同样的问题,如以下示例所示:

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();
        }
    }
}
关注者
0
被浏览
73
1 个回答
  • 面试哥
    面试哥 2021-01-30
    为面试而生,有面试问题,就找面试哥。

    对于TryWithResources该类,以下类产生与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();
            }
        }
    }
    

    使用Sun JDK 1.7.0,在这两个主要的方法字节码和异常表TryWithResourcesTryCatchFinally类是:

      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
    

    对于TryWithResources2该类,以下类产生与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();
            }
        }
    }
    

    TryWithResources2TryCatchFinally2类中主要方法的字节码和异常表是:

      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
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看