众所周知Java是的蓬勃兴起有一部分原因是因为Java的跨平台行,和优秀的内存管理,z这些都赖于其虚拟机的支持,所以虚拟机成为Java学习者跨步不去的坎。下图是对虚拟机整体的概述,可以使我们大体了解虚拟机到底做了那些事。因为虚拟机设计的知识实在是太多太细,我们肯定无法一次性将其讲清楚。我们接下来讲从面试的角度去思考去理解JVM。

第一个问题jvm内存模型(内存区域)

首先强调一下不是java内存模型,jvm内存模型和java内存模型是两个不同的概念。JVM 内存区域主要划分为线程私有区域【程序计数器、虚拟机栈、本地方法区】、线程共享区 域【JAVA 堆、方法区】、直接内存。如下图,jvm内存区域是java虚拟机规范定义的区域。最后具体怎么去实现还是要区分虚拟机。

方法区

存储被 JVM 加载的类信息、常量、静 态变量、即时编译器编译后的代码等数据.

是被线程共享的一块内存区域,创建的对象和数组都保存在 Java 堆内存中,也是垃圾收集器进行 垃圾收集的最重要的内存区域。

程序计数器

一块较小的内存空间, 是当前线程所执行的字节码的行号指示器,每条线程都要有一个独立的

程序计数器,这类内存也称为“线程私有”的内存。

正在执行 java 方法的话,计数器记录的是虚拟机字节码指令的地址(当前指令的地址)。如 果还是 Native 方法,则为空。

虚拟机栈

是描述 java 方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stack Frame) 用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成 的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

本地方法栈 本地方法区和 Java Stack 作用类似, 区别是虚拟机栈为执行 Java 方法服务, 而本地方法栈则为 Native 方法服务。

分配的内存总不能任由其增长,所以引出第二个问题jvm的垃圾回收机制。

怎么才能确认垃圾呢

引用计数法:在 Java 中,引用和对象是有关联的。如果要操作对象则必须用引用进行。因此,很显然一个简单 的办法是通过引用计数来判断一个对象是否可以回收。简单说,即一个对象如果没有任何与之关 联的引用,即他们的引用计数都不为 0,则说明对象不太可能再被用到,那么这个对象就是可回收 对象。(Redis的内存管理就是用的这种回收机制)

可达性分析:为了解决引用计数法的循环引用问题,Java 使用了可达性分析的方法。通过一系列的“GC roots”

对象作为起点搜索。如果在“GC roots”和一个对象之间没有可达路径,则称该对象是不可达的。要注意的是,不可达对象不等价于可回收对象,不可达对象变为可回收对象至少要经过两次标记 过程。两次标记后仍然是可回收对象,则将面临回收。

怎么去回收呢?

标记清除算法(Mark-Sweep) 最基础的垃圾回收算法,分为两个阶段,标注和清除。标记阶段标记出所有需要回收的对象,清 除阶段回收被标记的对象所占用的空间。如下图,该算法最大的问题是内存碎片化严重,后续可能发生大对象不能找到可利用空间的问题。

复制算法:为了解决 Mark-Sweep 算法内存碎片化的缺陷而被提出的算法。按内存容量将内存划分为等大小 的两块。每次只使用其中一块,当这一块内存满后将尚存活的对象复制到另一块上去,把已使用 的内存清掉,如图:

这种算法虽然实现简单,内存效率高,不易产生碎片,但是最大的问题是可用内存被压缩到了原 本的一半。且存活对象增多的话,Copying 算法的效率会大大降低。

标记整理算法:结合了以上两个算法,为了避免缺陷而提出。标记阶段和 Mark-Sweep 算法相同,标记后不是清 理对象,而是将存活对象移向内存的一端。然后清除端边界外的对象。如图:

上面介绍的是几种对垃圾处理的基本思路,各自有各自的优缺点。为了更高效的执行垃圾回收,分代收集法是目前大部分 JVM 所采用的方法,其核心思想是根据对象存活的不同生命周期将内存 划分为不同的域,一般情况下将 GC 堆划分为老生代(Tenured/Old Generation)和新生代(Young Generation)。老生代的特点是每次垃圾回收时只有少量对象需要被回收(所以一般采用整理或者标记清楚),新生代的特点是每次垃 圾回收时都有大量垃圾被回收,存活的对象较少(复制算法),根据各自分区的特点将垃圾回收的性能发挥到极致。

常见的垃圾回收器

下图是目前虚拟机支持的垃圾回收器,以及他们之间组合使用的关系。

Serial 垃圾收集器(单线程、复制算法)

Serial(英文连续)是最基本垃圾收集器,使用复制算法,曾经是 JDK1.3.1 之前新生代唯一的垃圾 收集器。Serial 是一个单线程的收集器,它不但只会使用一个 CPU 或一条线程去完成垃圾收集工 作,并且在进行垃圾收集的同时,必须暂停其他所有的工作线程,直到垃圾收集结束。

Serial 垃圾收集器虽然在收集垃圾过程中需要暂停所有其他的工作线程,但是它简单高效,对于限 定单个 CPU 环境来说,没有线程交互的开销,可以获得最高的单线程垃圾收集效率,因此 Serial

垃圾收集器依然是 java 虚拟机运行在 Client 模式下默认的新生代垃圾收集器。

ParNew垃圾收集器 ParNew 垃圾收集器其实是 Serial 收集器的多线程版本,也使用复制算法,除了使用多线程进行垃 圾收集之外,其余的行为和 Serial 收集器完全一样,ParNew 垃圾收集器在垃圾收集过程中同样也 要暂停所有其他的工作线程。

ParNew 收集器默认开启和 CPU 数目相同的线程数,可以通过-XX:ParallelGCThreads 参数来限 制垃圾收集器的线程数。【Parallel:平行的】

ParNew 虽然是除了多线程外和 Serial 收集器几乎完全一样,但是 ParNew 垃圾收集器是很多 java 虚拟机运行在 Server 模式下新生代的默认垃圾收集器。

Parallel Scavenge 收集器 Parallel Scavenge 收集器也是一个新生代垃圾收集器,同样使用复制算法,也是一个多线程的垃 圾收集器,它重点关注的是程序达到一个可控制的吞吐量(Thoughput,CPU 用于运行用户代码 的时间/CPU 总消耗时间,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)), 高吞吐量可以最高效率地利用 CPU 时间,尽快地完成程序的运算任务,主要适用于在后台运算而

不需要太多交互的任务。自适应调节策略也是 ParallelScavenge 收集器与 ParNew 收集器的一个 重要区别。

SerialOld收集器(单线程标记整理算法) Serial Old 是 Serial 垃圾收集器年老代版本,它同样是个单线程的收集器,使用标记-整理算法, 这个收集器也主要是运行在 Client 默认的 java 虚拟机默认的年老代垃圾收集器。

ParallelOld收集器(多线程标记整理算法) Parallel Old 收集器是 Parallel Scavenge 的年老代版本,使用多线程的标记-整理算法,在 JDK1.6 才开始提供。

CMS收集器(多线程标记清除算法)Concurrent mark sweep(CMS)收集器是一种年老代垃圾收集器,其最主要目标是获取最短垃圾 回收停顿时间,和其他年老代使用标记-整理算法不同,它使用多线程的标记-清除算法。

最短的垃圾收集停顿时间可以为交互比较高的程序提高用户体验。

G1收集器 Garbage first 垃圾收集器是目前垃圾收集器理论发展的最前沿成果G1 收集器避免全区域垃圾收集,它把堆内存划分为大小固定的几个独立区域,并且跟踪这些区域 的垃圾收集进度,同时在后台维护一个优先级列表,每次根据所允许的收集时间,优先回收垃圾 最多的区域。区域划分和优先级区域回收机制,确保 G1 收集器可以在有限时间获得最高的垃圾收 集效率。(大堆更友好)

上面的这些都是原理性的只能是基石,为下期我们分享JVM调优做准备,大家如果在开发过程,和学习中有什么疑问可以留言,也可以私信我。大家一起成长一起学习

java 指定垃g1圾收集_Java知识梳理--JVM相关推荐

  1. java 指定垃g1圾收集_java垃圾回收G1收集器

    G1(Garbage First)收集器是当今收集器技术发展的最前沿成果之一,他是一款面向服务端的垃圾收集器,它的使命是(在比较长期的)未来可以替换掉CMS收集器.它的特点如下: 1.并行与并发:G1 ...

  2. java 指定垃g1圾收集_【译】Java 14 Hotspot 虚拟机垃圾回收调优指南

    本文主要包括以下内容:优化目标与策略(Ergonomics) 垃圾收集器实现(Garbage Collector Implementation) 影响垃圾收集性能的因素总堆(Total Heap) 年 ...

  3. java 全局变量 内存不回收_JAVA知识梳理:内存管理与垃圾回收机制

    相对于C,C++来说,java程序员最幸运的事就是不用进行内存控制,很少会出现内存溢出的异常.但是这也不是绝对的,当出现oom的时候,如果不了解虚拟机是如何使用内存的,排查错误将会成为一项艰难的任务. ...

  4. java写值日表_Java知识之JVM

    类加载器 类装载器ClassLaoder负责加载class文件,class文件开头有特定的文件标识,将class文件字节码内容加载到内存中,并将这些内容转换成方法区中的运行时数据结构,并且ClassL ...

  5. JVM-垃圾回收篇-知识梳理

    文章目录 一. 前言 二.代码中的内存申请和回收 2.1 C语言版本 2.2 Java版本 三.给对象分配内存那点事 3.1 JVM的内存划分 3.2 GC堆 3.3 GC的分类 3.4 内存分配与回 ...

  6. java要频繁调用容器时_Java知识点梳理

    1.Struts2和SpringMVC的区别 (1)设计理念:前者为有状态的Action(均为多例),Action对象属性字段承载请求.响应,后者一般为无状态的Controller,请求直接封装到方法 ...

  7. java 是用什么写的_java里的jvm是用什么语言写的

    JAVA里的jvm虚拟机用的是C语言+汇编语言开发的.在此之上就是JAVA本身了,虚拟机是起到解析作用. 另外,JAVA并不比C语言慢,说JAVA慢一般是九十年代那时候的JAVA. 现在一段优秀的JA ...

  8. java虚拟机收集器_Java虚拟机(JVM)垃圾回收器G1收集器 - Break易站

    G1收集器 G1(Garbage-First)是JDK7-u4才推出商用的收集器: 1.特点 (A).并行与并发 能充分利用多CPU.多核环境下的硬件优势: 可以并行来缩短"Stop The ...

  9. java g1的并行_Java 11好用吗

    原标题:Java 11好用吗 开源规划调度引擎 OptaPlanner 官网发布了一个 Java 11 GC 性能基准测试报告. 当前使用量最大的 Java 版本是 8,所以测试者用 Java 8 与 ...

最新文章

  1. messenger android 4.,AndroidIPC机制(4)-Messenger
  2. vfp字符转换数值_JS数据类型转换与字面量
  3. php开启openssl的方法
  4. 当知识图谱遇上推荐系统(总述和推荐)
  5. win10系统电脑wifi图标不见了的开启方法
  6. linux python3安装教程_linux python3安装
  7. 互联网寒冬来袭,有一家公司却逆流而上!
  8. java frame_如何在java中建立frame
  9. 6 大技巧帮助初学者快速掌握 JavaScript!
  10. linux shell 流程控制(条件if,循环【for,while】,选择【case】语句实例
  11. 陷阱:使用==来比较原始的包装器对象,如Integer
  12. SI9000差分阻抗计算示例
  13. TeamViewer安装——好用的远程办公软件
  14. android studio 使用xml:app命名空间代码不提示问题
  15. 红外遥控风扇改手机APP远程控制杂记
  16. android卡在gradle,Android Studio打开新项目卡在Gradle的问题
  17. win10使用ssh指令传输文件
  18. EmguCV入门(一)
  19. PreferenceActivity和PreferenceFragment实现设置界面
  20. Mysql使用大全(MySQL架构与存储引擎 、事务 、业务设计 、索引 、数据结构 、执行计划 、数值类型)

热门文章

  1. VS2008中C++打开Excel(MFC)
  2. python入职要求_Python入职面试,可能会被企业HR问到的问题,你准备好了吗
  3. C/S和B/S模式的主要特点以及区别在那里?画出CGI工作原理图,具体描述CGI的主要流程和实现步骤。
  4. 内蒙古大学计算机组成原理难吗,内蒙古大学计算机组成原理期末练习0.doc
  5. Custom Depth in Unreal Engine 4
  6. [DirectX11]Gerstner波 实现简单的水面模拟
  7. go-elasticsearch: Elastic官方的Go语言客户端
  8. Laravel 使用 scout 集成 elasticsearch 做全文搜索
  9. 如何应对内网安全的那些新挑战——威胁不断,防御不止
  10. mfc ctabctrl 双排显示_盐城便宜的开口型双排脚手架生产厂家-斯戴博盘扣脚手架...