bytecode difference for finally block

Viewed 97

The same source code is compiled on the server and locally, generating different bytecodes for finally block

Bytecode compiled by the server:

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

Locally compiled bytecode:

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

Two more lines of statement for the server version:

L71
LINENUMBER 245 L71

What factors may cause this difference?

Source code:

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 Answers

The two bytecode paths between them are identical. However, the former looks like it's got an extra entry in the LineNumberTable attribute.

If you use javap -v -c on the class, you'll see that the actual body of the bytecode is identical between the two.

I've recently given a talk on the way bytecodes work; on page 15 of the deck you'll see that the LineNumberTable attribute is an addition to the method:

Picture of bytecode showing LineNumberTable attribute

So the question is why the compiler is doing different things. It's possible that you're using a different set of compile options (e.g. -g or -O although the latter has very little difference).

It's possibly more likely that you're not using the same compiler, even though the JDK is the same. For example, your local machine you might be compiling with javac while the server is compiling with mvn (or vice versa). Typically tools like Tomcat will use a different compiler based off of ecj rather than deferring to the system compiler, and it's possible that's what the difference is between the two.

Related