jvm:运行期优化

运行期优化

  • 即时编译:

    • 分层编译:将执行状态分成了5个层次;

      • 0层,采用解释执行【interpreter】;

      • 1层,使用C1即时编译器编译执行【不带profiling】;

      • 2层,使用C1即时编译器编译执行【带基本profiling】;

      • 3层,使用C1即时编译器编译执行【带完全profiling】;

      • 4层,使用C2即时编译器编译执行;

        profiling:在运行过程中收集一些程序执行状态的数据,例如,方法调用的次数,循环的次数;

        效率:interpreter < C1 < C2

    • 即时编译器【JIT】与解释器的区别:

      • 解释器将字节码解释为机器码,下次遇到相同当字节码,也会执行重复的解释;
      • JIT是将一些字节码编译为机器码,并存入 Code Cache,下次遇到相同代码,直接执行,无需要编译;
      • 解释器,是针对所有平台,通用的机器码;
      • JIT,会根据平台类型,生成平台特定的机械码【针对小部分热点代码,Hotspot】;
  • 优化手段:逃逸分析

    • 发现新建对象是否会被引用,当不存在引用的时候【那就是生产垃圾】,底层优化后,可能就不产生对象了;
  • 方法内联:

    • 当发现热点方法,而且长度不会太长,就会进行内联:把方法内代码拷贝,粘贴到调用的位置【节约一个栈帧】;
    • 进一步,当发现有常数一直在进行运算的时候,能够进行常量折叠的优化,直接保存常量结果;
  • 字段优化

    • 对局部变量的访问速度要快于成员变量和静态变量,所有尽可能使用局部变量操作【当发生字段优化时,就会将成员变量先复制给局部变量,然后从局部变量获取】;

    • 方法内联会影响字段优化;

      //elements成员数组; 
      for (int i=0, i < elements.length, i++) {
          dusum(elements[i]);
      }
      //字段优化,jvm优化;
      int[] local = this.elements;
      for (int i=0, i < local.length, i++) {
          dusum(local[i]);
      } 
      //编译器优化,效果相同
      for (int i : elements) {
          dusum(i);
      } 
      
  • 反射优化:

    • 反射方法的调用,是通过本地方法的方法访问器进行调用;
    • 当调用一共达到16次的时候,jvm会自动生成动态方法访问器,对于静态方法,其内部是使用 类名.方法的常规调用形式;
posted @ 2025-03-20 10:41  烟雨断桥  阅读(7)  评论(0)    收藏  举报