【问题标题】:bytecode difference for finally blockfinally 块的字节码差异
【发布时间】:2020-10-16 23:06:45
【问题描述】:

在服务器端和本地编译相同的源码,为finally块生成不同的字节码

服务器编译的字节码:

L70
 LINENUMBER 243 L70
 INVOKESTATIC com/demo/utils/DashboardManager.log (Ljava/lang/String;JLjava/util/Map;)V
L71
 LINENUMBER 245 L71
 ALOAD 9
 ATHROW
L47
 LINENUMBER 246 L47
FRAME CHOP 2
 ALOAD 2
 ARETURN

本地编译的字节码:

L70
 LINENUMBER 243 L70
 INVOKESTATIC com/demo/utils/DashboardManager.log (Ljava/lang/String;JLjava/util/Map;)V
 ALOAD 9
 ATHROW
L47
 LINENUMBER 246 L47
FRAME CHOP 2
 ALOAD 2
 ARETURN

服务器版本多两行声明:

L71
LINENUMBER 245 L71

哪些因素可能导致这种差异?

源代码:

235:        } catch (Exception ex) {
236:            CLogManager.error(logLocal, ex, addInfo);
237:            response = BuildServiceResponse.BuildErrorResponse(UserInfoStatusCode.ServerException, ex.getMessage());
238:        } finally {
239:            metricTags.put("status", null == response ? "-1" : response.resultMsg);
240:            metricTags.put("code", null == response ? "-1" : String.valueOf(response.resultCode));
241:            DashboardManager.log(TokenServiceMetric.GetUserInfoShare_RequestCount, 1, metricTags);
242:            DashboardManager.log(TokenServiceMetric.GetUserInfoShare_ResponseCount, 1, metricTags);
243:            DashboardManager.log(TokenServiceMetric.GetUserInfoShare_CostTime,
244:                    System.currentTimeMillis() - beginTime, metricTags);
245:        }
246:        return response;
247:    }

【问题讨论】:

  • 每种情况下使用了哪些 javac 版本(包括次要版本)?
  • 我看到的唯一区别是“隐形”重新投掷归因于哪一行,我想说无论如何基本上没有意义。生成不同的字节码是一个问题还是你只是好奇?如果这是一个问题,那么您当然必须确保双方使用完全相同的软件和配置才能有机会获得相同的字节码。
  • @Michael 都是 1.8.0-144

标签: java jvm code-coverage bytecode try-catch-finally


【解决方案1】:

它们之间的两个字节码路径是相同的。但是,前者看起来在 LineNumberTable 属性中多了一个条目。

如果你在类上使用javap -v -c,你会看到字节码的实际主体在两者之间是相同的。

我最近given a talk 了解字节码的工作方式;在卡片组的page 15 上,您会看到 LineNumberTable 属性是该方法的补充:

所以问题是为什么编译器会做不同的事情。您可能正在使用一组不同的编译选项(例如 -g-O,尽管后者几乎没有区别)。

您可能没有使用相同的编译器,即使 JDK 相同。例如,您的本地计算机可能使用javac 进行编译,而服务器使用mvn 进行编译(反之亦然)。通常,像 Tomcat 这样的工具将使用基于 ecj 的不同编译器,而不是遵循系统编译器,这可能就是两者之间的区别。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-11
    • 2014-01-08
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多