专栏首页大数据进阶jvm(1):jvm内存模型

jvm(1):jvm内存模型

身为一个职业的Java程序员,每天打交到最多的就是jvm,那么套用孙子的一句话“知己知彼方能百战不殆”,熟悉jvm也就意味着是我们进阶路上必过之槛,下面先来张图,大概说明下jvm的内存分布

从图上可以看出Java内存主要分5个部分,下面会针对这5个部分分别进行说明

方法区:主要是保存的信息是类的元数据。方法区与堆空间类似,是被JVM中所有的线程共享的区域。方法区中最为重要的是类的类型信息、常量池、域信息、方法信息。类型信息包括类的完整名称、父类的完整名称、类型修饰符和类型的直接接口。常量池包括类方法、域等信息所引用的常量信息。域信息包括域名称、域类型和域修饰符、方法信息包括方法名称、返回类型、方法参数、方法修饰符、方法字节码、操作数栈和方法栈帧的局部变量区大小以及异常表。方法区是线程间共享的,当两个线程同时需要加载一个类型时,只有一个类会请求ClassLoader加载,另一个线程则会等待。

Java堆:堆在JVM规范里是一种通用性的内存池,用于存放所有的Java对象。堆是一个运行时数据区,类的对象从中分配空间,堆的优势是可以动态地分配内存大小,生存周期也不需要事先告诉编译器。

因为这里讲到了Java堆,所有有必要讲一下Java堆的优化,1是将生命周期较长的Java对象从heap中移到heap之外,并且GC不能管理GCIH内部的Java对象,以此达到降低GC的回收频率和提升GC的回收效率的目的,另外逃逸分析与栈上分配这样的优化技术同样也是降低GC回收频率和提升GC回收效率的有效方式。

下面来说下逃逸分析。如果一个对象的指针被多个方法或线程引用时,那就可以称这个指针发生了逃逸

public class escapeAnalysisClass{ public static B b; public void globalVariablePointerEscape(){//给全局变量赋值,发生逃逸 b = new B(); } public B methodPointerEscape(){//方法返回值,发生逃逸 return new B(); } public void instancePassPointerEscape(){ methodPointerEscape().printClassName(this);//实例引用发生逃逸 } }

通过上面的例子我们可知,逃逸分析通常是全局变量赋值、方法返回值、实例引用传递(详见另一篇文章)

虚拟机栈:JVM的架构是基于栈的,即程序指令的每一个操作都要经过入栈和出栈这样的组合型操作才能完成。虚拟机栈是一种可以被用来快速访问的存储区域,该区域位于通用RAM里面,通过使用它的所谓的“”栈指针”,可以访问处理器。栈是一种快速有效的分配存储方法,访问速度仅次于寄存器,堆栈指针若向下移动,则分配新的内存,若向上移动,则释放那些内存。由于Java虚拟机需要预先去生成相应的内存空间,所以但我们尝试运行程序的时候,Java虚拟机必须知道被存储在栈内的所有数据的确切大小和生命周期,以便按照上面陈述的分配存储方法通过上下移动堆栈指针来动态调整内存空间。

综上对比堆和栈,可知栈的优势是访问速度比堆要快,它仅次于寄存器,并且栈数据是可以被共享的。栈的缺点是存储在栈里面的数据大小与生存期必须是确定的,从这一点来看,栈明显缺乏灵活性。

Java虚拟机栈也是线程私有的内存空间,它和Java线程在同一时间创建,它保存方法的局部变量、部分结果,并参与方法的调用和返回。

再来深入探讨虚拟机栈的内部结构。

虚拟机栈在运行时使用一种叫作栈帧的数据结构保存上下文数据,栈帧里面存放了方法的局部变量表、操作数栈、动态链接方法和返回地址等信息。每一个方法的调用都伴随着栈帧的入栈操作,相对的,方法的返回则表示栈帧的出栈操作。如果方法调用时,方法的参数和局部变量相对较多,那么栈帧中的局部变量表就会比较大,栈帧会不断膨胀以满足方法调用所需传递的信息增大需求。

栈帧由三部分组成,即局部变量取,操作数栈和帧数据区。

程序计数器:当前线程所执行的字节码的行号指示器。在多线程环境下,为了让线程切换后能恢复到正确的执行位置,每个线程都要一个独立的程序计数器,各个线程之间互不影响、独立存储,因此这块内存是线程私有的。

本地方法栈:本地方法栈用于管理本地方法的调用。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • dubbo源代码解析之-集群容错

    Failover Cluster:失败自动切换,当出现失败,重试其它服务器,通常用于读操作(推荐使用)

    yiduwangkai
  • 【译】Envoy threading model

    原文链接:https://blog.envoyproxy.io/envoy-threading-model-a8d44b922310

    yiduwangkai
  • AtomicIntegerFieldUpdater

    对于volatile变量,写的时候会将线程本地内存的数据刷新到主内存上,读的时候会将主内存的数据加载到本地内存里,所以可以保证可见行和单个读/写操作的原子性。但...

    yiduwangkai
  • Bistoury原理解析

    今天想和大家聊聊Java中的APM,简单介绍Java中的Instrumentation技术,然后重点分析bistoury的实现原理

    spilledyear
  • Java多线程:神秘的线程变量 ThreadLocal 你了解吗?

    Carson.Ho
  • 浅谈原理--hashCode方法

    每增加一个元素,我们就可以通过equals方法判断集合中的每一个元素是否重复,但是如果集合中有10000个元素了,我们每添加一个元素的时候,就需要进行10000...

    Arebirth
  • 怎么理解变量

    我们都知道计算机很厉害,可以干很多事情,可以玩游戏,可以解题,可以播放音乐,可以画画,可以控制火箭卫星等等。为什么计算机可以干这么多不同的事情,它又是如何做到的...

    用户7054460
  • SAS-Macro 中的那些语句(二)

    昨天哪一篇说了宏变量定义的三种方式(SAS-Macro 中的那些语句(一)),今天接着昨天的说...还是围绕着宏变量进行展开,第一个问题,宏变量的作用域有限制么...

    Setup
  • Chromium内核版Edge浏览器已开放下载

    EDGE是英文Enhanced Data Rate for GSM Evolution 的缩写,即增强型数据速率GSM演进技术。微软专门为新IE打造的引擎,速度...

    爱游博客
  • 机器学习:XGBoost 安装及实战应用

    《实例》阐述算法,通俗易懂,助您对算法的理解达到一个新高度。包含但不限于:经典算法,机器学习,深度学习,LeetCode 题解,Kaggle 实战。期待您的到来...

    double

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动