Java代码的运行

2020-11-12  本文已影响0人  纸箱子的一

为什么Java代码需要在虚拟机中运行

Java虚拟机怎样运行字节码

分两个视角:

Java虚拟机的运行效率

根据二八定律,其实大部分的代码是不需要提前编译的,是可以直接解释执行的。仅需将少部分的热点代码进行编译,达到提升效率。
为了满足不同客户的需求,HotSpot内置了多个即时编译器:C1、C2 和 Graal。在编译时间和生成代码的执行效率之间进行取舍。

再回顾一下Java内存区域划分

Java虚拟机运行时将内存划分为5个部分:方法区、堆、PC寄存器、Java方法栈和本地方法栈

对于热点代码的判断可看链接

JVM会统计每个方法被调用了多少次,超过多少次,那就是热点方法。(还有个循环回边计数器,用来编译热循环的。) 默认的分层编译应该是达到两千调C1,达到一万五调C2。
https://mp.weixin.qq.com/s/GO2fAeGgaB2jIC02gWp5Aw
分享一个工具 asmtools 可以修改字节码指令文件
https://ci.adoptopenjdk.net/view/Dependencies/job/asmtools/lastSuccessfulBuild/

public class Foo {
    public static void main(String[] args) {
        boolean flag = true;
        if(flag){
            System.out.println("Hello,Java");
        }
        if(flag==true){
            System.out.println("Hello,JVM");
        }
    }
}
super public class Foo
        version 52:0
{
  public Method "<init>":"()V"
        stack 1 locals 1
  {
                aload_0;
                invokespecial   Method java/lang/Object."<init>":"()V";
                return;
  }
  public static Method main:"([Ljava/lang/String;)V"
        stack 2 locals 2
  {
                iconst_1;  //@1 用asmtools 工具将此处修改为 iconst_2 那么程序输出结果为 Hello,Java。
                istore_1;
                iload_1;
                ifeq    L14;
                getstatic       Field java/lang/System.out:"Ljava/io/PrintStream;";
                ldc     String "Hello,Java";
                invokevirtual   Method java/io/PrintStream.println:"(Ljava/lang/String;)V";
        L14:    stack_frame_type append;
                locals_map int;
                iload_1;
                iconst_1;
                if_icmpne       L27;
                getstatic       Field java/lang/System.out:"Ljava/io/PrintStream;";
                ldc     String "Hello,JVM";
                invokevirtual   Method java/io/PrintStream.println:"(Ljava/lang/String;)V";
        L27:    stack_frame_type same;
                return;
  }

} // end Class Foo

jvm把boolean当做int来处理
flag = iconst_1 = true
修改后flag改为iconst_2
if(flag)比较时ifeq指令做是否为零判断,常数2仍为true,打印输出
if(true == flag)比较时if_cmpne做整数比较,iconst_1是否等于flag,比较失败,不再打印输出。
-- 这个来自极客时间中的评论。

上一篇 下一篇

猜你喜欢

热点阅读