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

堆和栈是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. verilog if语句

    a.基本形式 1) if(表达式) 语句1: 2)if(表达式) 语句1: else 语句1 3) if(表达式1) 语句1: else   if(表达式2) 语句2: else   if(表达式3) ...

  2. 如何修改FlashFXP默认编辑工具使用记事本打开

    FlashFXP如果不设置默认编辑工具,那么当你打开html文档的时候,默认会用word打开,很不方便,其实简单的设置下,可以默认以任何工具打开.具体设置方法如下: 选项>>关联文件. 然 ...

  3. IA-32e模式下的异常处理

    系统异常处理 CPU如果调用系统异常处理程序 需要的数据结构 IDT_Table: 中断向量表, 在中断向量表中的每一项都是一个中断描述符(中断门或者陷阱门), 一个中断描述符中的几位是段选择符 GD ...

  4. linq to entity 左连接 右连接 以及内连接写法的区别

    左连右连还是内连这个其实你不需要关心.只需要根据实体的映射关系写查询,框架会自动帮你生成的. 至于linq查询语法与扩展方法的效率,应该是一样的,比如: var users=(from u in db ...

  5. Android开发由eclipse转Android Studio中一些常见出错问题解决方法

    1.给一个Activity添加了一个Dialog主题,结果出现了下面的问题,在eclipse却没有出错 <activity android:name=".DialogActivity& ...

  6. python模块详解 logging

    打印日志的五个级别: import logging logging.debug('test debug') logging.info('test info') logging.warning('tes ...

  7. Oracle 数据库自动备份方案

    1.新建 backup.bat脚本 @echo off echo ================================================ echo Windows环境下Ora ...

  8. 01、Spark安装与配置

    01.Spark安装与配置 1.hadoop回顾 Hadoop是分布式计算引擎,含有四大模块,common.hdfs.mapreduce和yarn. 2.并发和并行 并发通常指针对单个节点的应对多个请 ...

  9. socks v5 协议解析

    socks v5是一种用于代理的协议,就是说client用这种协议与server沟通,让server帮忙代访问remote后再将结果通过此协议返给client,所以一般是涉及到3个端,分别是clien ...

  10. C++ Eigen库和Matlab对比

    // A simple quickref for Eigen. Add anything that's missing. // Main author: Keir Mierle #include &l ...