相同的源代码在服务器上和本地编译,为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: }
答案 0 :(得分:0)
它们之间的两个字节码路径相同。但是,前者似乎在LineNumberTable
属性中有一个额外的条目。
如果在类上使用javap -v -c
,则会发现字节码的实际主体在两者之间是相同的。
我最近given a talk介绍了字节码的工作方式;在卡片组的page 15上,您会看到LineNumberTable属性是该方法的补充:
所以问题是为什么编译器会做不同的事情。您有可能使用了不同的编译选项集(例如-g
或-O
,尽管后者几乎没有什么区别)。
即使JDK相同,也很有可能您没有使用相同的编译器。例如,当服务器使用javac
进行编译时,您可能使用mvn
进行编译的本地计算机(反之亦然)。通常,像Tomcat
这样的工具会基于ecj
使用不同的编译器,而不是推迟使用系统编译器,这可能就是两者之间的区别。