一、堆和栈的速度性能分析

堆和栈是JVM内存模型中的2个重要组成部分,自己很早以前也总结过堆和栈的区别,基本都是从存储内容,存储空间大小,存储速度这几个方面来理解的,但是关于堆和栈的存储速度,只知道堆存储速度慢,栈存储速度快,至于为什么堆比栈的存取速度慢,并没有特别深入的研究,从网上也找了很多资料,但很多理由并不太认同,这里也列举一些,并结合自己的理解来分析,如果不正确欢迎指正。

1、从分配的角度分析

java中栈的大小和生命周期在编译期间就确定了的(可以参考之前写的一篇JVM内存模型中的分析,本周末会写一篇该系列知识点中GC策略和GC收集器的博客),而堆是在运行时动态分配的,这会花不少时间,因此从分配的角度来说,堆比栈速度慢。

2、从访问角度分析

网上很多文章都说访问栈只需1次,而访问堆需要2次,一次取地址,第二次根据地址去访问对象,这个观点我并不是完全认同。我们知道,虚拟机栈中存储的是一个个栈帧,每个栈帧中存储的是一些局部变量表,操作数,动态链接和返回地址等,当访问栈的时候,一次访问就可以获取这些数据,而java中访问堆对象的方式主要有2种:通过直接指针和句柄访问,直接指针的方式有点类似于数组的首地址,通过直接指针能快速找到这个对象,只需1次访问。这种方式相比句柄的好处是速度更快,但缺点也很明细:当进行GC的时候,地址会发生变化,而GC是很频繁的。另一种方式是句柄,句柄就相当于一个小区的门卫,当你要找这个小区里的某个住户时(这个住户很有钱很任性,每天住在不同的楼层和房间),你要先去找门卫,门卫会告诉你这个人他今天在哪栋楼哪个房间,然后你再到这个房间去找就行了。这样一来你就需要访问2次(1次门卫,再根据门卫去找住户)。这样速度自然就慢了,但这种方式的好处就是:通过门卫你永远都能知道这个住户在哪里,不管住户怎么变(GC过程中对象会频繁移动,导致地址会频繁变更)。因此我的理解应该是:如果堆使用的是直接指针的方式的话,从访问角度来说,应该区别不大,当然如果是句柄的方式,倒有些道理。

3、从CPU命中率角度分析

我们知道CPU有3级缓存,一级缓存速度最快,接近CPU的速度,但是一级缓存比较小,二级缓存速度次之,空间稍大,三级缓存速度又慢些,空间又大些,而且CPU读取的时候是按行来读取的,比如64位的机器每次读取的就是64位,相当于每次可以读取2个int类型的长度,每次读取某个数据的时候,可能会把相邻的数据一块读取进来,而栈占用的空间小,这样CPU的命中率会更高些,而且淘汰率会更低,而堆占用的空间大,相对来说,每次读取命中率更低了,淘汰率也更高,因此从这个角度来说,栈也比堆要快写。

上面说的是堆和栈的存储速度区别,下面再来分析下静态方法和非静态方法的速度比较。

       二、静态方法和非静态方法(已经创建对象前提下)执行性能分析

其实之前的直觉是静态方法的访问速度应该会比非静态方法快,因为静态方法在加载类的时候就存到方法区了,运行时可以直接调用,而非静态方法调用时需要先初始化对象再来调用,那问题来了:假如对象已经初始化了,再调用静态方法和非静态方法哪个快呢?开始以为非静态方法要快,因为非静态方法是存储在虚拟机栈中的,而栈的访问速度是比较快的,但是这并不严谨,那就来个实验吧。

下图是多次运行的结果:

第一次:

第二次:

第三次:

第四次:

可以看到,循环10000次的结果里,非静态方法的执行速度4次里有3次都比静态方法快。再来个100000次的循环看看结果:

第一次:

第二次:

第三次:

第4次:

这个就更明显了,所以就实验结果而言,如果在已经创建对象的前提下,非静态方法的访问速度是比静态方法的访问速度快的。但是至于原因,上面的理由感觉还是有点勉强,依旧不是很清楚,欢迎各位大神指点

Java中堆、栈,静态方法和非静态方法的速度问题的更多相关文章

  1. Java中 堆 栈,常量池等概念解析(转载)

    1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符 ...

  2. java中静态方法和非静态方法调用的一点小困扰,已解决。

    public static void main(String[] args) { // TODO Auto-generated method stub SimpleGui1B gui=new Simp ...

  3. Java中synchronized用在静态方法和非静态方法上面的区别

    synchronized 修饰在 static方法和非static方法的区别   在Java中,synchronized是用来表示同步的,我们可以synchronized来修饰一个方法.也可以sync ...

  4. 在java中静态方法与非静态方法

    在java中public void与public static void有什么区别 ? public void 修饰是非静态方法,该类方法属于对象,在对象初始化(new Object())后才能被调用 ...

  5. Java中堆内存和栈内存详解2

    Java中堆内存和栈内存详解   Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,ja ...

  6. Java中堆和栈的区别(转)

    栈与堆都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆.      Java的堆是一个运行时数据区,类的对象从中分配空间.这些对象通过new. ...

  7. 转 C#中静态方法与非静态方法区别比较

    C#静态方法与非静态方法的区别不仅仅是概念上的,那么他们有什么具体的区别呢?让我们通过本文向你做一下解析. C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他们在使用 ...

  8. Java中堆与栈

    简单的说:Java把内存划分成两种:一种是栈内存,一种是堆内存. 1:什么是堆内存: 堆内存是是Java内存中的一种,它的作用是用于存储Java中的对象和数组,当我们new一个对象或者创建一个数组的时 ...

  9. Java中堆(heap)和栈(stack)的区别

    简单的说: Java把内存划分成两种:一种是栈内存,一种是堆内存. 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配. 当在一段代码块定义一个变量时,Java就在栈中为这个变量分 ...

随机推荐

  1. Kudu-Master的设计

    不多说,直接上干货! http://blog.csdn.net/lookqlp/article/details/70858466

  2. Linux小知识(1): bash中执行数据库的相关操作

    工作中经常会遇到命令行操作数据库或登陆至其他服务器等情况,往往需要通过命令行进入相关的数据库或登陆至相关的服务器,再执行指令操作,因此有没有方法,在命令行或bash脚本中模拟进入数据库或登陆服务器操作 ...

  3. UVA 10462 —— Is There A Second Way Left?——————【最小生成树、kruskal、重边】

    Nasa, being the most talented programmer of his time, can’t think things to be so simple. Recently a ...

  4. Ibatis.net 1.6.2 简单配置及Log4.Net日志记录

    看似简单的Ibatis配置起来注意的地方还挺多.里面的设置及功能还算强大.昨晚配置了半宿,结果一运行还是各种错误.急的直冒汗.果断下载实例去研究.英文不好文档只能作为功能参考. 下面一步步进入Ibat ...

  5. 让DIV的滚动条自动滚动到最底部

    一个在线聊天窗口,在做最后的修饰时,需要对获得的信息即时滚动以保证用户总能看到最新消息. 我得出的结论是:在选中div时,必须用原生js,jQuery不起作用 <!DOCTYPE> < ...

  6. 当尝试从ArcCatalog、.net应用或是Java应用中连接ArcGIS Server 时,显示下面任何一种错误提示: "Access Denied" 或 "The connection could not be made"

    Error: 访问拒绝或无法连接错误 文章编号 : 29042 软件: ArcGIS Server 9.0, 9.1, 9.2, 9.3, 9.3.1 操作系统: Windows 2000, XP, ...

  7. js获取农历日期【转】

    var CalendarData=new Array(100); var madd=new Array(12); var tgString="甲乙丙丁戊己庚辛壬癸"; var dz ...

  8. mvc中尽量避免使用HttpContext.Current.Request

    在Mvc开发中滥用HttpContext.Current.Request,可能会造成非IE浏览器重复加载页面的情况. 不管你信不,反正我在Mvc3.0中遇到过.

  9. Mono For Android如何在VS2012 中打开设计界面

      刚接触 Mono For Android 没几天,不知不觉把设计界面弄丢了.辛辛苦苦才把设计界面弄出来,如果你在 Layout 下打开 *.xaml 的文件打开的却是 xml 文档,那么你可以按照 ...

  10. tcpdump确认服务器连接的交换机信息

    Displaying CDP info via tcpdump or snoop Cisco Discovery Protocol is a management protocol that Cisc ...