普通进程栈区,在JVM一般仅仅用做线程栈,如下图所示

首先是永久代。永久代本质上是Java程序的代码区和数据区。Java程序中类(class),会被加载到整个区域的不同数据结构中去,包括常量池、域、方法数据、方法体、构造函数、以及类中的专用方法、实例初始化、接口初始化等。这个区域对于操作系统来说,是堆的一个部分;而对于Java程序来说,这是容纳程序本身及静态资源的空间,使得JVM能够解释执行Java程序。

其次是新生代和老年代。新生代和老年代才是Java程序真正使用的堆空间,主要用于内存对象的存储;

那么这些区域如何对应JVM的内存模型呢,首先看一张经典的JVM内存模型图:

线程栈:在JVM中用做线程栈,每个线程都会在这个区域开辟私有栈

程序计数器是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器,字节码解释器通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支循环,跳转,异常处理,线程恢复等基础功能,特别注意的是,如果线程正在执行的是一个java方法那这个计数器记录的是字节码指令的地址(位置),如果是执行的是Native方法,这个计数器为空

程序计数器该部分内存是唯一不会发生OutOfMemoryError异常的区域

java虚拟机栈,也在这个线程栈中,线程私有,每个方法执行的同时都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息.

局部变量表,存放了编译期可知的各种基本数据类型(boolean,byte,char short,int float,long,double),对象引用(reference,指向对象的指针,或者代表对象的句柄)和returnAddress类型

在jvm规范中,对这个区域规定了两种异常状况:1.如果线程请求的的栈深度大于虚拟机所允许的深度,将抛出StackOverFlowError异常,如果虚拟机栈可以动态扩展,扩展时无法申请到足够的内存将抛出OutOfMemoryError异常

本地方法栈,与虚拟机栈的作用非常相似,只不过是服务于Native方法,也会抛出两种异常

inux的普通进程所使用的堆区,在jvm(Hotspot)进程中分为永久新生老年代三块区域

永久代,对应于 jvm的方法区,

方法区:用于存储已经被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码,等数据.要特别注意的是.方法区和永久代并不是等价的,这要取决于虚拟机的类型,紧紧是因为HotSpot使用永久代来实现方法区.对于其他虚拟机并不存在永久代的概念,

运行时常量池是方法区的一部分,因此它也在永久代,用于存储编译期间生成的各种字面量和符号引用,什么叫字面量呢,就是int i =1;这个1就是字面量,String str= "abc";这个abc是字面量,什么叫符号引用呢,就是在一个类中Student stu = new Student("张三",28) new出来的Student对象在编译后未加载前显然不知道其实际内存地址,因此在class文件中用一串无异议的符号来代替对象的内存首地址,等class文件经过一系列的加载检验之后分配完内存,会将符号引用替换成直接引用

新生代和老年代

Java堆:新生代和老年代才是对应于JVm内存模型中的java堆,它是被所有线程共享的一个内存区域,在虚拟机启动时创建.它的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存,包括数组

java堆是垃圾收集器管理的主要区域,因此,很多时候也被称为GC堆,由于现在收集器基本都采用分代收集算法,所以Java堆细分为新生代和老年代;再细致一点的有Eden空间,FROM Survivor空间,To Survivor空间等.

从内存分配的角度来看,线程共享的java堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer TLAB),进一步划分是为了更好的回收内存,或者更快的分配内存.

根据JVM规范,java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的就可以,如果在堆中内有内存完成实例分配,并且对无法扩展出足够的内存,将会抛出OutOfMemoryError异常

JVM中的直接内存,并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用,而且也可能导致OutOfMemoryError,

在jdk1.4中新加入了NIO类,引入了一种基于通道(Channel)与缓冲区(BUffer)的IO方式,它可以使用Native函数库直接分配内存,然后通过一个存储在java堆中的DirectByteBuffer对象作为这块内存引用进行操作,这样能在一些场景中显著提高性能,因为避免了Java堆和Native堆中来回复制数据.如下图:NIO使用的堆外内存

显然,本机直接内存的分配不会受到Java堆大小的限制,但是,既然是内存,肯定还是会受到本机总存的(包括RAM以及swap区域或者分页文件),大小以及处理器寻址空间的限制.服务器管理员在配置虚拟机参数时,会根据实际内存设置-Xmx等参数信息.但经常忽略直接内存,使得各个内存区域总和大于物理内存限制(包括物理的和操作系统级的限制),从而导致动态扩展时出现OutOfMemoryError异常

https://mp.weixin.qq.com/s?__biz=MzI4NTEzMjc5Mw==&mid=2650554703&idx=1&sn=4b2ce0d3fa9017adb2dac9843f097882&chksm=f3f833d9c48fbacf242749ec8f40197d9ea5463dc46f47afc62fd93b3fe4f433a723ceddd515#rd

从linux进程角度看JVM内存模型的更多相关文章

  1. 【JVM】上帝视角看JVM内存模型,分而治之论各模块详情

    1. 上帝视角 [树看JVM] [图看JVM] 2. 分而治之 2.1 堆区 构成:堆区由新生代和老年代组成,新生代中包含伊甸区(Eden).幸存者区(survivor from .survivor ...

  2. JVM内存模型你只要看这一篇就够了

    JVM内存模型你只要看这一篇就够了 我是一只孤傲的鱼鹰 让我们不厌其烦的从内存模型开始说起:作为一般人需要了解到的,JVM的内存区域可以被分为:线程栈,堆,静态方法区(实际上还有更多功能的区域,并且这 ...

  3. Inside JVM 内存模型

    Inside JVM 内存模型 来源  原文:https://blog.csdn.net/silentbalanceyh/article/details/4661230 参考:IBM开发中心文档,&l ...

  4. JVM内存模型 三

    本文章节: 1.JMM简介 2.堆和栈 3.本机内存 4.防止内存泄漏   1.JMM简介 i.内存模型概述 Java平台自动集成了线程以及多处理器技术,这种集成程度比Java以前诞生的计算机语言要厉 ...

  5. JVM内存模型与GC算法(简介)

    JVM内存模型如上图,需要声明一点,这是<Java虚拟机规范(Java SE 7版)>规定的内容,实际区域由各JVM自己实现,所以可能略有不同.以下对各区域进行简短说明. 1.1程序计数器 ...

  6. JVM的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集

    (转自:http://my.oschina.net/u/436879/blog/85478) 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认 ...

  7. [转]JVM内存模型

    最近排查一个线上java服务常驻内存异常高的问题,大概现象是:java堆Xmx配置了8G,但运行一段时间后常驻内存RES从5G逐渐增长到13G #补图#,导致机器开始swap从而服务整体变慢.由于Xm ...

  8. JVM内存模型小结

    JVM运行时的数据区域划分图如下,该图是JVM内存模型最主要的内容. 从图中可以看出来,JVM将内存主要划分为五个部分:程序计数器.Java虚拟机栈.本地方法栈.Java堆和方法区.这些被划分为用途不 ...

  9. JVM内存模型和性能优化 转

    JVM内存模型和性能优化 JVM内存模型优点 内置基于内存的并发模型:      多线程机制 同步锁Synchronization 大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于 ...

随机推荐

  1. Deploy a plain HTTP registry

    当docker pull a.b.com/ubuntu:14.04的时候,如果提示:“Docker x509 insecure registry”之类的,说这个registry不安全的,如果就是想在a ...

  2. github 体积限制

    github 体积限制 仅供了解,切勿滥用.希望自觉维护良好社区. 单文件 单个文件大于 50M 时会收到警告, 100M 时会被拒绝. 该警告将告诉您哪些文件太大: remote: warning: ...

  3. Superset配置impala数据源

    1.安装impyla pip install impyla 2.在superset页面配置如下,此时impala是有kerberos认证的 impala://xxxx:xx/default?auth_ ...

  4. Invoke 和 BeginInvoke 的真正涵义

    BeginInvoke 方法真的是新开一个线程进行异步调用吗? 参考以下代码: public delegate void treeinvoke(); private void UpdateTreeVi ...

  5. [K8s] Kubernetes 是什么 不是什么

    现在有三种部署方式,传统物理机部署.虚拟机部署.容器化部署. 我们现在所使用的云上服务器一般都是虚拟化出来的,硬件资源独立,操作系统等软件资源亦独立. 容器化的好处是更轻量,复用下层的操作系统,相当于 ...

  6. panda读取Excel

    pandas读取Excel的第一种方法 方法一:默认读取第一个表单 import pandas print("\n方法一:") xls_data=pd.read_excel('ce ...

  7. jquery+css 点赞喜欢特效

    百度盘链接 https://pan.baidu.com/s/1Nu8fiUrdffsNd6usTsUESg 密码 mps4 效果:

  8. GO指南练习:切片

    最近开始GO语言的学习,在GO指南中练习到切片这个题目 练习:切片 实现 Pic.它应当返回一个长度为 dy 的切片,其中每个元素是一个长度为 dx,元素类型为 uint8 的切片.当你运行此程序时, ...

  9. Mysql的常见索引

    PRIMARY KEY(主键索引) ALTER TABLE table_name ADD PRIMARY KEY ( col ) 它是一种特殊的唯一索引,不允许有空值: UNIQUE(唯一索引) AL ...

  10. Oracle学习笔记(四)

    Oracle中的体系结构: oracle体系结构中的进程: 共享池相关的优化: drop table t purge; create table t as select * from dba_obje ...