jvm

103 阅读3分钟

jvm逃逸分析:

错误理解

对象都分配在堆上,由于栈上只能保存基本类型,所以不能存储对象。

解释

当JVM开启逃逸分析时,如果jvm检测到当前对象只在当前线程使用,不需要放到堆中。即没有逃逸.

但是由于栈上只能分配基本类型,所以需要对对象进行标量替换,如Obj对象会被拆分为两个标量(scalar) i和j,分配在堆上;

class Obj{
int i;
int j
}

分析

经过逃逸分析,使线程独享的对象分配在栈上,降低了对堆空间的使用,当重复添加对象时有效降低了GC的次数;

但是在

Escape Analysis,对象仅在当前方法使用没有被其他方法引用即没有逃逸;

当jvm有实时编译JIT just in time), 如果jvm有开启逃逸分析,如果当前对象经过逃逸分析没有逃逸,则说明当前对象无需分配到堆上,反正是线程独享;

会做一些优化如: 标量替换 栈上分配

将一个对象拆分成多个标量(scalar),分配在栈上;

即时编译(JIT just in time)

解释

一个java程序的需要先将源码编译成字节码,再将字节码解释成机器码才能给系统执行。这样就有一个天然的缺陷 方法每次执行都要解释成机器码一次才能执行。 为了优化执行的效率,产生了即时编译,即时编译就是jvm记录当前方法执行的次数如果达到一定的阈值则将此方法解释的机器码保存在jvm中,之后再调用就不需要重新解释了。 而这个阈值可以通过-XX:CompileThreshold=N指定;

编译模式

  1. client模式
  2. sever模式
  3. 分层编译 client模式编译速度快,但是编译之后的机器码运行速度比servce模式的慢; server模式解释的出的机器码质量较高但是速度较慢。 分层编译是指由于server模式的即时编译阈值(CompileThreshold)大于client模式的阈值,所以代码会先以client模式编译,提高编译速度,如果该方法的调用次数达到了server的阈值则再次编译,保障机器码的运行速度。

编译方式

  1. 编译方法
  2. 编译循环

编译方法是指统计方法的调用次数来和CompileThreshold比较; 编译循环是指jvm会判断当前这个方法内的循环如果循环次数超过了CompileThreshold,则JIT会只编译这个循环而不是整个方法;

编译线程

JIT工作是全程在后台执行的,编译线程的个数可以通过-XX:+CICompilerCount=N来强制指定;

代码缓存

编译后的代码存在缓存中,而缓存的大小是可以限定的,如果超出了限定值则不会在进行JIT了,大小可以通过 XX:ReservedCodeCacheSize指定