当前位置: 首页 > 面试题库 >

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

燕璞
2023-03-14
问题内容

我试图通过使用常规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();
        }
    }
}

问题答案:

对于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


 类似资料:
  • 问题内容: 我读到try-with-resources 中的块是可选的。我试图在try-with- resources块中创建一个对象,没有后续块,只是从eclipse中获取编译器错误:“ 自动调用引发了未处理的异常类型。” 由于可以在try-with- resources中使用的每个资源都实现了,因此在调用该方法时可能会引发异常,因此我不明白该子句是可选的,因为它不允许我跳过从中捕获异常的过程。

  • 如何重写下面的代码 使用try-catch-finally构造? 如果我们只创建一个资源,这里有一个很好的链接。 不幸的是,当我们创建多个资源时,我不明白如何概括这一点。 我不明白的一件事是,我们如何认识到发生在上的事情没有发生在'b'上,反之亦然。

  • 我读到try-with资源中的块是可选的。我尝试在try-with资源块中创建一个对象,没有后续的块,只是从eclipse中获取编译器错误:“由自动调用引发的未处理异常类型。” 由于每一个资源,可以使用在try与资源实现,因此潜在地抛出一个异常调用方法,我不明白如何子句是可选的,因为它不允许我跳过从捕获异常。 是否有一些特殊要求,即AutoCloseable的具体实现不直接声明其方法中抛出的任何异

  • 下面的try with resources语句是来自Java文档的示例 根据文件, 用资源尝试语句确保每个资源在语句末尾关闭。 我的问题是,为什么我需要在try关键字之后立即在括号内声明资源。(如上面的BuffereReader) BufferReader实现了java。lang.AutoCloseable 所以为什么不支持这样的事情, 一旦退出尝试,就隐式关闭资源对象。(正如它所实现的自动关闭)

  • 我正在Sonarqube上运行我的JDBC代码。我的代码有问题。 上面说3号线和9号线有阻塞问题。使用try-with-resources或在“finally”子句中关闭此“PreparedStatement”。我不明白这一点。我不知道如何解决这个问题

  • 主要内容:Java SE 7:Try-With-Resources基础知识,Java SE 7:Try-With-Resources规则,Java SE 9:Try-With-Resources改进在这篇文章中,我们将讨论Java SE 9中的一些改进语句。现在让我们开始学习这个构造。 Java SE 7:Try-With-Resources基础知识 Java SE 7引入了一个新的构造: 语句,用于更好的异常处理。 如果没有这个构造,开发人员必须编写大量冗余和难看的代码。 如果开发人员忘记正确