最近看了周志明版本的《深入理解Java虚拟机》第一版和第二版,写的很好,收获很多,此处总结一下。
 
jvm中内存划分:
 
如上图,一共分为五块,其中:
线程共享区域为:
1、java堆
2、方法区
 
线程私有区域为:
3、JVM栈
4、本地方法栈
5、程序计数器
 
各区域作用:
1、java堆:
    java堆是jvm内存管理中最大的一块,线程共享。在jvm启动的时候创建。此区域唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。但是随着JIT编译器(即时编译器)的发展与逃逸分析技术的逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙变化(对象可能会分配到栈上),所以这种所有对象都分配在堆上也不是那么绝对的。
    java堆细分为新生代和老年代,新生代又分为Eden空间、From Survivor空间、To Survivor空间,新生代中垃圾回收算法为复制算法,复制算法是先将内存分为连个部分,一部分用来放入对象,而另一部分暂时不用,当使用的一部分内存要进行垃圾回收的时候会将不需要回收的对象复制保存在另一个空间中,然后再对使用过的那部分区域进行垃圾回收,这样虽然效率很高,但是很浪费空间,所以一般将新生代分为Eden空间和两个Survivor空间,其大小在HotSpot虚拟机中默认比例为8:1:1,这样在新生代中采用复制算法回收垃圾效率就很高了,具体回收过程是将Eden区域和From Survivor区域作为对象的存储空间,当要进行垃圾回收的时候先将这两个区域中不需要回收的对象复制保存在To Survivor区域中,然后再进行垃圾回收。另外有一点是当一个对象在Eden区域和From Survivor区域中存储的时候发现内存不足,这时会进行内存分配担保,就是将此对象直接存入在老年代中。
    老年代中采用的GC算法为标记-清除算法或者标记-整理算法。标记-清除算法为:首先标记出要进行GC的对象,标记完成后再进行GC。这种算法效率不高,并且会产生很多内存碎片。标记-整理算法:同样是先对要进行GC的对象进行标记,但是不同的是在标记完成后不是立刻执行GC,而是先将不需要GC的对象移动到一端,然后在边界外再对要回收的对象进行GC。
    关于对象的分配:对象优先在Eden区域分配,大对象会直接进入老年代,长期存活的对象会进入老年代,这里的长期存活是根据新生代中的对象年龄阈值来定义的,对象刚分配到新生代的时候年龄为1,每进行一次GC对象的年龄会加1,HotSpot中默认的阈值是15,也就是说对象年龄达到15岁的时候会被分配到老年区,这个值是可以通过参数配置的。
    在进行垃圾回收的时候新生代GC又叫minor GC,老年代GC可以设置内存容量达到百分比的多少的时候进行GC,老年代的GC又叫Full GC,minor GC时间短,频率高,而Full GC时间长,频率低。
 
2、方法区
    方法区又被称为永久区,线程共享,是用来存储已被JVM加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区为堆的一个逻辑部分,但是在JDK1.7的HotSpot中已经将方法区中的字符串常量池移出,部分资料显示JDK1.8已经去除了方法区(不确定)。不过已经可以猜测此区域将会被本地内存逐步取代。
    这个区域很少进行垃圾回收,回收目标主要是针对常量池的回收和对类型的卸载。
 
3、JVM栈
    JVM栈是线程私有的,它的生命周期与线程相同。JVM栈描述的是java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
    局部变量表中存放了编译期可知的各种基本数据类型、对象的引用类型。局部变量表中需要的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。
 
4、本地方法栈
    本地方法栈和JVM栈非常相似,它们之间的区别不过是jvm栈是为执行java方法服务,而本地方法栈是为jvm使用到对的本地方法服务。HotSpot虚拟机中直接把本地方法栈和JVM栈合二为一了。
 
5、程序计数器
    程序计数器是一块较小的内存空间,线程私有。它可以看作是当前线程所执行的字节码的行号指示器。在jvm的概念模型里,字节码解释器工作就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
    如果线程正在执行的是一个java方法,这个计数器记录的是正在执行的jvm字节码指令的地址;如果正在执行的是本地方法,这个计数器值则为空。
 
总结:
    在jvm划分的内存区域中JVM栈和本地方法栈可能会抛出StackOverflowError异常和OutOfMemoryError异常。java堆和方法区可能会抛出OutOfMemoryError异常。程序计数器中没有地方规定会抛出这两个异常。
 
扩展:
    在jvm规范中,StackOverflowError异常为:如果线程请求的栈深度大于JVM允许的栈深度,将抛出StackOverflowError异常。OutOfMemoryError异常:如果jvm可以动态扩展,如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。
    HotSpot虚拟机中标记要清除的对象方法不是使用引用计数器(有引用的时候计数器+1,引用失效-1,应用为0时回收),而使用的是可达性分析算法:以“GC Roots“的对象为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明这个对象不可达,即这个对象不可用,所以这个对象会被判定为是可回收对象。
 
标记-清除算法处理前后:
 
 
复制算法处理前后:
 
 
标记-整理算法处理前后:
 
 

jvm的内存分配总结的更多相关文章

  1. JVM初探- 内存分配、GC原理与垃圾收集器

    JVM初探- 内存分配.GC原理与垃圾收集器 标签 : JVM JVM内存的分配与回收大致可分为如下4个步骤: 何时分配 -> 怎样分配 -> 何时回收 -> 怎样回收. 除了在概念 ...

  2. JVM总结(二):JVM的内存分配策略

    这节我们总结一下JVM中的内存分配策略.目录如下: 内存分配策略 对象优先在新生代Eden分配 大对象直接进入老年代 长期存活的对象将进入老年代 动态对象年龄判定 空间分配担保 内存分配策略 Java ...

  3. JVM的内存分配垃圾回收策略

    之前看过<深入了解Java虚拟机>感觉容易忘,今天写一篇博客加深一下印象. JVM的内存分配和垃圾回收(GC)主要发生在Java堆中.而Java堆根据对象的存活时间可以分为新生代和老年代, ...

  4. 一夜搞懂 | JVM GC&内存分配

    前言 本文已经收录到我的Github个人博客,欢迎大佬们光临寒舍: 我的GIthub博客 学习导图 一.为什么要学习GC&内存分配? 时代发展到现在,如今的内存动态分配与内存回收技术已经相当成 ...

  5. JVM的内存分配与垃圾回收策略

    自动内存管理机制主要解决了两个问题:给对象分配内存以及回收分配给对象的内存. >>垃圾回收的区域 前面的笔记中整理过虚拟机运行数据区,再看一下这个区域: 注意在这个Runtime Data ...

  6. 浅谈JVM与内存分配

    一.程序内存分配 初始内存分配 当一个程序准备运行时,它首先向java虚拟机要内存,但是java虚拟机本身没有权限,它只能向操作系统申请内存,此时java虚拟机会拥有一个初始内存, 此处额外说明一下e ...

  7. jvm对象内存分配

    一.jvm简单结构图 1.jvm内存对象分配整体流程: 1.类加载子系统和方法区 类加载子系统负责从文件系统或者网络中加载Class信息,加载的类信息存放于一块称为方法区的内存空间.除了类的信息外, ...

  8. 【面试必备】小伙伴栽在了JVM的内存分配策略。。。

    周末有小伙伴留言说上周面试时被问到内存分配策略的问题,但回答的不够理想,小伙伴说之前公号里看过这一块的文章的,当时看时很清楚,也知道各个策略是干嘛的,但面试时脑子里清楚,心里很明白,但嘴里就是说不清楚 ...

  9. 认识JVM的内存分配

    当我们在JVM中运行一段程序代码,JVM初始运行的时候都会分配好Method Area(方法区)和Heap(堆),而JVM每遇到一个线程,就为其分配一个Program Counter Register ...

随机推荐

  1. Spring学习(二)

    1. AOP的思想(如何实现),AOP在哪些地方使用? 相关术语有哪些? AOP是面向切面编程,它是一种编程思想,采取横向抽取机制,取代了传统纵向继承体系重复性代码的方式 应用场景有: 记录日志 监控 ...

  2. ORA-12541:TNS:no listener 客户端tnsnames.ora配置,以及服务端listener.ora配置

    需求:客户端(192.168.25.1)需要访问服务端(192.168.7.215)的Oracle库ORCL. 步骤一:配置客户端tnsnames.ora 步骤二:配置服务端listener.ora ...

  3. DataTable 只保留想要的几列

    using System; using System.Collections; using System.Configuration; using System.Data; using System. ...

  4. 剑指Offer-【面试题03:二维数组中的查找】

    package com.cxz.question3; /* * 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序. * 请完成一个函数,输入这样的一个二维数组和 ...

  5. HDU5988 Coding Contest(费用流)

    2016青岛现场赛的一题,由于第一次走过不会产生影响,需要拆点,不过比赛时没想到,此外还有许多细节要注意,如要加eps,时间卡得较紧要注意细节优化等 #include <iostream> ...

  6. IIS设置默认主页无效

    服务器系统:Windows server 2008 R2 IIS版本:7.5 IIS中部署一个dotnet framework 3.5的网站应用程序,设置"默认文档"为:index ...

  7. 前端知识杂烩(Javascript篇)

    1. JavaScript是一门什么样的语言,它有什么特点?2.JavaScript的数据类型都有什么?3.请描述一下 cookies,sessionStorage 和 localStorage 的区 ...

  8. Android传递数据5种方法

       Android开发中,在不同模块(如Activity)间经常会有各种各样的数据需要相互传递,我把常用的几种 方法都收集到了一起.它们各有利弊,有各自的应用场景. 我现在把它们集中到一个例子中展示 ...

  9. VS2013如何避开安装时IE10的限制

    [VS2013]如何避开VS2013必须要有IE10的限制 VS就会告诉我们目前环境不适合安装VS2013,必须升级IE版本到IE10. 在不安装IE10时的时候,安装办法: 将下面一段文字,储存为. ...

  10. Vue - 实例

    1.实例属性介绍如下图所示: 具体介绍如下: A.$parent:访问当前组件的父实例 B.$root:访问当前组件的根实例,要是没有的话,则是自己本身 C.$children:访问当前组件实例的直接 ...