1、堆和栈的速度性能分析html
堆和栈是JVM内存模型中的2个重要组成部分,本身很早之前也总结过堆和栈的区别,基本都是从存储内容,存储空间大小,存储速度这几个方面来理解的,可是关于堆和栈的存储速度,只知道堆存储速度慢,栈存储速度快,至于为何堆比栈的存取速度慢,并无特别深刻的研究,从网上也找了不少资料,但不少理由并不太认同,这里也列举一些,并结合本身的理解来分析,若是不正确欢迎指正。java
一、从分配的角度分析数组
java中栈的大小和生命周期在编译期间就肯定了的(能够参考以前写的一篇JVM内存模型中的分析,本周末会写一篇该系列知识点中GC策略和GC收集器的博客),而堆是在运行时动态分配的,这会花很多时间,所以从分配的角度来讲,堆比栈速度慢。缓存
二、从访问角度分析性能
网上不少文章都说访问栈只需1次,而访问堆须要2次,一次取地址,第二次根据地址去访问对象,这个观点我并非彻底认同。咱们知道,虚拟机栈中存储的是一个个栈帧,每一个栈帧中存储的是一些局部变量表,操做数,动态连接和返回地址等,当访问栈的时候,一次访问就能够获取这些数据,而java中访问堆对象的方式主要有2种:经过直接指针和句柄访问,直接指针的方式有点相似于数组的首地址,经过直接指针能快速找到这个对象,只需1次访问。这种方式相比句柄的好处是速度更快,但缺点也很明细:当进行GC的时候,地址会发生变化,而GC是很频繁的。另外一种方式是句柄,句柄就至关于一个小区的门卫,当你要找这个小区里的某个住户时(这个住户颇有钱很任性,天天住在不一样的楼层和房间),你要先去找门卫,门卫会告诉你这我的他今天在哪栋楼哪一个房间,而后你再到这个房间去找就好了。这样一来你就须要访问2次(1次门卫,再根据门卫去找住户)。这样速度天然就慢了,但这种方式的好处就是:经过门卫你永远都能知道这个住户在哪里,无论住户怎么变(GC过程当中对象会频繁移动,致使地址会频繁变动)。所以个人理解应该是:若是堆使用的是直接指针的方式的话,从访问角度来讲,应该区别不大,固然若是是句柄的方式,倒有些道理。3d
三、从CPU命中率角度分析指针
咱们知道CPU有3级缓存,一级缓存速度最快,接近CPU的速度,可是一级缓存比较小,二级缓存速度次之,空间稍大,三级缓存速度又慢些,空间又大些,并且CPU读取的时候是按行来读取的,好比64位的机器每次读取的就是64位,至关于每次能够读取2个int类型的长度,每次读取某个数据的时候,可能会把相邻的数据一块读取进来,而栈占用的空间小,这样CPU的命中率会更高些,并且淘汰率会更低,而堆占用的空间大,相对来讲,每次读取命中率更低了,淘汰率也更高,所以从这个角度来讲,栈也比堆要快写。htm
上面说的是堆和栈的存储速度区别,下面再来分析下静态方法和非静态方法的速度比较。对象
2、静态方法和非静态方法(已经建立对象前提下)执行性能分析blog
其实以前的直觉是静态方法的访问速度应该会比非静态方法快,由于静态方法在加载类的时候就存到方法区了,运行时能够直接调用,而非静态方法调用时须要先初始化对象再来调用,那问题来了:假如对象已经初始化了,再调用静态方法和非静态方法哪一个快呢?开始觉得非静态方法要快,由于非静态方法是存储在虚拟机栈中的,而栈的访问速度是比较快的,可是这并不严谨,那就来个实验吧。
下图是屡次运行的结果:
第一次:
第二次:
第三次:
第四次:
能够看到,循环10000次的结果里,非静态方法的执行速度4次里有3次都比静态方法快。再来个100000次的循环看看结果:
第一次:
第二次:
第三次:
第4次:
这个就更明显了,因此就实验结果而言,若是在已经建立对象的前提下,非静态方法的访问速度是比静态方法的访问速度快的。可是至于缘由,上面的理由感受仍是有点勉强,依旧不是很清楚,欢迎各位大神指点