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

堆和栈是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. GCC操作

    GCC编译器常用选项 生成动态链接库: gcc file.c -fPIC -o file.so, PIC表示Position-Independent Code: 独立地址代码 编译: gcc -c f ...

  2. MyEclipse 比较常用的快捷键

    Ctrl+D: 删除当前行 Alt+↓ 当前行和下面一行交互位置(特别实用,可以省去先剪切,再粘贴了) Alt+↑ 当前行和上面一行交互位置(同上) Alt+← 前一个编辑的页面 Alt+→ 下一个编 ...

  3. python的数字

    1.整数 与其它语言不同点两个乘号(**)代表 乘方运算 .前面代表底数,后面代表指数. 2.浮点数 它的小数位数可能是不确定的,需要注意 3.使用str()避免错误 在输出字符串时,可以避免类型错误 ...

  4. ACM-单调队列用于DP优化

    http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 待续

  5. [精校版]The Swift Programming Language--语言指南--字符串和字符 (转)

    今天装了10.10.马上就可以实际编写swift了.还是很兴奋啊. 哈哈.字符串和字符是大家最容易打交道的.今天就转一下讲解swift中字符串和字符的文章.希望对大家有帮助. 原文地址:http:// ...

  6. 浅谈python的深浅拷贝

    python中有两种数据类型:一种是可变数据类型,一种是不可变数据类型 不可变数据类型包括(整型及其他数据类型,字符串及元组) 可变数据类型(列表,集合,字典,类和类实例) 鉴定是否为拷贝还是只是引用 ...

  7. (生产)vuex - 状态管理

    参考:https://vuex.vuejs.org/zh-cn/ 安装 直接下载 / CDN 引用 https://unpkg.com/vuex在 Vue 之后引入 vuex 会进行自动安装:< ...

  8. jQueryMobile(一)

    一].jQuery Mobile 页面 <!DOCTYPE html> <html lang="zh-cn"> <head> <meta ...

  9. WorkFlow 的 Xaml 中找不到引用类型

    原来还是需要两步走. 1. 在refernece里面应用project或dll. 2. 在xaml的命名空间里面手动添加.

  10. Quartz .Net(定时框架):

    Quartz .Net(定时框架): 基本说明: 说明:Quartz .Net 是一个从 Java 版的 Quartz 移植过来定时任务框架,可以实现异常灵活的定 时任务 用法: 安装 Quartz ...