最终块的字节码差异

时间:2020-06-26 10:51:44

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

相同的源代码在服务器上和本地编译,为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:    }

1 个答案:

答案 0 :(得分:0)

它们之间的两个字节码路径相同。但是,前者似乎在LineNumberTable属性中有一个额外的条目。

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

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

Picture of bytecode showing LineNumberTable attribute

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

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

相关问题