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

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

问题描述

假设我们有以下类:

public class Message extends Object {}公共类记录器实现 ILogger {public void log(Message m) {/*空*/}}

以及以下程序:

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

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

解决方案

Java 编译器会删除语句 ab 吗?

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

<块引用>

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

符合 JLS :-).

从实用的角度来看:

  • 如果 javac 编译器优化了这些调用,Java 调试器将根本看不到它们......这会让开发人员感到困惑.
  • 如果 Message 类和主类是独立编译/修改的,早期优化(通过 javac)会导致损坏.例如,考虑这个序列:

    • Message 已编译,
    • 编译主类,
    • Message 被编辑,以便 log 做一些事情......并重新编译.

    现在我们有一个错误编译的主类,它在 ab 处没有做正确的事情,因为过早的内联代码已经过时了.

<小时>

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

  • ab 中的方法调用可能会被内联,如果 JIT 编译器可以推断出不需要虚拟方法分派.(如果 Logger 是应用程序使用的唯一实现 ILogger 的类,那么这对于一个好的 JIT 编译器来说是显而易见的.)

  • 内联第一个方法调用后,JIT 编译器可能会确定主体是一个 noop 并优化调用.

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

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

Let's imagine we have the following classes:

public class Message extends Object {}

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

and the following program:

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

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 ?

解决方案

Will the Java compiler strip out statements a and b ?

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.)

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

Conformance with the JLS :-).

From a pragmatic perspective:

  • 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:

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

    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.


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

  • 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.)

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

  • 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.

(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天全站免登陆