JAVA中堆、栈,静态方法和非静态方法的速度问题

 更新时间:2018年08月02日 09:03:09   作者:曦阳x  
这篇文章主要介绍了JAVA中堆、栈,静态方法和非静态方法的速度问题,堆和栈得速度性能分析多角度给大家分析,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下

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

       堆和栈是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次的循环看看结果:

    第一次:

   第二次:

 

    第三次:

   第四次:

    这个就更明显了,所以就实验结果而言,如果在已经创建对象的前提下,非静态方法的访问速度是比静态方法的访问速度快的。但是至于原因,上面的理由感觉还是有点勉强,依旧不是很清楚,欢迎各位大神指点。如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • 在springboot 中使用 AIService的方法

    在springboot 中使用 AIService的方法

    这篇文章主要介绍了在springboot 中使用 AIService的方法,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2025-04-04
  • Java使用Tesseract-OCR实战教程

    Java使用Tesseract-OCR实战教程

    本文介绍了如何在Java中使用Tesseract-OCR进行文本提取,包括Tesseract-OCR的安装、中文训练库的配置、依赖库的引入以及具体的代码实现,通过这个过程,我们将演示如何从视频帧中提取文本
    2025-02-02
  • java中的快捷键小结

    java中的快捷键小结

    以下是myeclipse中的所有快捷键列表
    2013-03-03
  • JAVA编程不能不知道的反射用法总结

    JAVA编程不能不知道的反射用法总结

    这篇文章主要介绍了Java反射技术原理与用法,结合实例形式分析了Java反射技术的基本概念、功能、原理、用法及操作注意事项,需要的朋友可以参考下
    2021-07-07
  • 基于swagger测试List类型参数过程详解

    基于swagger测试List类型参数过程详解

    这篇文章主要介绍了基于swagger测试List类型参数过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • SpringBoot整合spring-retry实现接口请求重试机制及注意事项

    SpringBoot整合spring-retry实现接口请求重试机制及注意事项

    今天通过本文给大家介绍我们应该如何使用SpringBoot来整合spring-retry组件实现重试机制及注意事项,本文通过实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2021-08-08
  • JAVA socket.io注解原理及用法图解

    JAVA socket.io注解原理及用法图解

    这篇文章主要介绍了JAVA socket.io注解原理及用法图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • 基于springboot 配置文件context-path的坑

    基于springboot 配置文件context-path的坑

    这篇文章主要介绍了基于springboot 配置文件context-path的坑,基于很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • 在SpringBoot中使用YourKit进行性能调优的教程详解

    在SpringBoot中使用YourKit进行性能调优的教程详解

    在应用程序的开发过程中,性能调优是一个重要的环节,在SpringBoot应用程序中,我们可以使用YourKit来进行性能调优,YourKit是一款非常强大的Java性能调优工具,在本文中,我们将介绍如何在 SpringBoot应用程序中使用YourKit进行性能调优
    2023-06-06
  • Spring Boot Admin的使用详解(Actuator监控接口)

    Spring Boot Admin的使用详解(Actuator监控接口)

    这篇文章主要介绍了Spring Boot Admin的使用详解(Actuator监控接口),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05

最新评论