Java:JVM如何优化对void和empty函数的调用? [英] Java: How will JVM optimise the call to a void and empty function?

查看:150
本文介绍了Java:JVM如何优化对void和empty函数的调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们假设我们有以下类:

Let's imagine we have the following classes:

public class Message extends Object {}

public class Logger implements ILogger {
 public void log(Message m) {/*empty*/}
}

以及以下程序:

public static void main(String args[]) {
  ILogger l = new Logger();
  l.log((Message)null); // a)
  l.log(new Message()); // b)
}

Java编译器是否会删除语句 a b ?在两种情况下(剥离或不剥离),Java编译器决定的基本原理是什么?

Will the Java compiler strip out statements a and b ? In both cases (stripping or not stripping), what is the rationale behind the Java compiler's decision ?

推荐答案


Java编译器是否会删除语句 a b

javac (字节码源代码)编译器不会剥离任何一个调用。 (通过检查字节码很容易检查;例如查看 javap -c 输出。)

The javac (source to bytecode) compiler won't strip either call. (It is easy to check this by examining the bytecodes; e.g. looking at the javap -c output.)


在这两种情况下(剥离或不剥离),Java编译器决定的理由是什么?

In both cases (stripping or not stripping), what is the rationale behind the Java compiler's decision ?

符合JLS :-)。

Conformance with the JLS :-).

从务实的角度来看:


  • 如果 javac 编译器优化了调用,Java调试器根本无法看到它们......这对开发人员来说相当混乱。

  • 如果消息类和主类被编译/早期优化(通过 javac )将导致破坏独立修改。例如,请考虑以下顺序:

  • If the javac compiler optimized the calls away, a Java debugger wouldn't be able to see them at all ... which would be rather confusing for the developer.
  • Early optimization (by javac) would result in breakage if the Message class and the main class were compiled / modified independently. For example, consider this sequence:


  • 消息已编译,

  • 编译主类

  • 编辑消息以便 log 做某事......然后重新编译。

  • Message is compiled,
  • the main class is compiled,
  • Message is edited so that log does something ... and recompiled.

现在我们有一个不正确编译的主类,但没有做 a b 是正确的,因为过早内联的代码已过期。

Now we have an incorrectly compiled main class that doesn't do the right thing at a and b because the prematurely inlined code is out of date.

但是,JIT编译器可能优化代码在运行时以各种方式。例如:

However, the JIT compiler might optimize the code at runtime in a variety of ways. For instance:


  • 该方法调用 a 和<$ c如果JIT编译器可以推断出不需要虚拟方法调度,则可以内联$ c> b 。 (如果 Logger 是实现 ILogger 的应用程序使用的唯一类,这对于一个好的JIT编译器来说是一个明智的选择。)

  • The method calls in a and b may be inlined if the JIT compiler can deduce that no virtual method dispatching is required. (If Logger is the only class used by the application that implements ILogger this a no-brainer for a good JIT compiler.)

在内联第一个方法调用之后,JIT编译器可以确定主体是noop并优化调用。

After inlining the first method call, the JIT compiler may determine that the body is a noop and optimize the call away.

在第二个方法调用的情况下,JIT编译器可以进一步推断(通过转义分析)消息对象不会不需要在堆上分配......或者根本不需要。

In the case of the second method call, the JIT compiler could further deduce (by escape analysis) that the Message object doesn't need to be allocated on the heap ... or indeed at all.

(如果你想知道JIT编译器(在您的平台上)实际的功能是什么,Hotspot JVM有一个JVM选项,可以为所选方法转储JIT编译的本机代码。)

(If you want to know what the JIT compiler (on your platform) actually does, Hotspot JVMs have a JVM option that dumps out the JIT-compiled native code for selected methods.)

这篇关于Java:JVM如何优化对void和empty函数的调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆