栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

优化过程中会使用Java内联方法吗?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

优化过程中会使用Java内联方法吗?

javac
将提供字节码,该字节码是生成该字节码的原始Java程序的忠实表示(在某些可以优化的特定情况下除外: 常量折叠消除死代码
)。但是,当JVM使用JIT编译器时,可以执行优化。

对于第一种情况,JVM似乎支持内联(请参见此处的“

方法”
下的内容,以及有关JVM的内联示例的信息,请参见此处)。

我找不到自己执行方法内联的任何示例

javac
。我尝试编译一些示例程序(类似于您在问题中描述的程序),即使是,它们似乎都没有直接内联该方法
final
。这些优化似乎是由JVM的JIT编译器而非进行的
javac
。下提到的“编译”
的方法
在这里似乎是热点JVM的JIT编译器,而不是
javac

据我所知,它

javac
支持 死代码消除 (请参阅第二种情况的示例)和 常量折叠
。在常量折叠中,编译器将预先计算常量表达式并使用计算出的值,而不是在运行时执行计算。例如:

public class ConstantFolding {   private static final int a = 100;   private static final int b = 200;   public final void baz() {      int c = a + b;   }}

编译为以下字节码:

Compiled from "ConstantFolding.java"public class ConstantFolding extends java.lang.Object{private static final int a;private static final int b;public ConstantFolding();  Code:   0:   aload_0   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V   4:   returnpublic final void baz();  Code:   0:   sipush  300   3:   istore_1   4:   return}

请注意,字节码有一个

sipush 300
替代
aload
getfield
S和一个
iadd
300
是计算值。
privatefinal
变量也是如此。如果
a
b
不是静态的,则产生的字节码将是:

Compiled from "ConstantFolding.java"public class ConstantFolding extends java.lang.Object{private final int a;private final int b;public ConstantFolding();  Code:   0:   aload_0   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V   4:   aload_0   5:   bipush  100   7:   putfield    #2; //Field a:I   10:  aload_0   11:  sipush  200   14:  putfield    #3; //Field b:I   17:  returnpublic final void baz();  Code:   0:   sipush  300   3:   istore_1   4:   return}

这里也

sipush 300
使用了。

对于第二种情况(消除死代码),我使用了以下测试程序:

public class InlineTest {   private static final boolean debug = false;   private void baz() {      if(debug) {         String a = foo();      }   }   private String foo() {      return bar();   }   private String bar() {      return "abc";   }}

给出以下字节码:

Compiled from "InlineTest.java"public class InlineTest extends java.lang.Object{private static final boolean debug;public InlineTest();  Code:   0:   aload_0   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V   4:   returnprivate void baz();  Code:   0:   returnprivate java.lang.String foo();  Code:   0:   aload_0   1:   invokespecial   #2; //Method bar:()Ljava/lang/String;   4:   areturnprivate java.lang.String bar();  Code:   0:   ldc #3; //String abc   2:   areturn}

如您所见,

foo
根本不会调用,
baz
因为该
if
块内的代码实际上是“死”的。

Sun(现在是Oracle)的HotSpot
JVM结合了字节码的解释和JIT编译。当将字节码提供给JVM时,代码将首先进行解释,但是JVM将监视字节码并挑选出经常执行的部分。它将这些部分覆盖到本机代码中,以便它们可以更快地运行。对于不经常使用的字节码,此编译不会完成。同样也因为编译有一些开销。因此,这实际上是一个权衡的问题。如果决定将所有字节码编译为本机代码,则该代码可能会具有很长的启动延迟。

除了监视字节码之外,JVM还可在解释和加载字节码时对其执行静态分析,以执行进一步的优化。

如果您想了解JVM执行的特定类型的优化,那么Oracle的此页面将非常有帮助。它描述了HotSpot
JVM中使用的性能技术。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/437515.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号