JVM复习

文章目录

  • JVM的内存区域
  • 怎么判断一个对象是否能被回收——GC Roots
    • 垃圾的定义
  • 垃圾回收机制
    • 什么时候开始回收
  • 垃圾收集器
    • 串行收集器
    • 并行收集器
  • Minor GC、Major GC和Full GC
  • 四种垃圾回收算法——分代收集算法
  • GC算法优劣标准
  • 双亲委派机制
    • 沙箱机制
    • 打破双亲委派机制
  • 引用的分类
  • OOM
  • 深入分析编译原理
  • 逃逸分析
  • 通过一个类的全限定名获得此类的统一资源定位符

JVM的内存区域

  • 程序计数器:线程私有。该区域是唯一一个在Java虚拟机规范中没有规定任何OOM情况的内存区域。记住 当前线程 的下一条 JVM字节码指令 的 执行地址 ,便于进行 线程切换
  • Java虚拟机栈:线程私有。
    • 栈帧:存储了局部变量表、操作数栈、动态连接和方法出口等信息。
  • 本地方法栈:线程私有。调用本地方法时使用的栈。Native方法不是以Java语言实现的,而是以本地语言实现的(c或c++)与操作系统底层交互。
  • :线程共享。在堆上的区域会被进一步划分为新生代和老年代等。Java虚拟机在启动的时候,可以使用Xmx参数指定堆区大小。主要存储使用new关键字创建的对象。
  • 方法区:线程共享。包括运行时常量池。用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码。常量池中存储各种字面量和符号引用,避免了频繁的创建和销毁对象,实现了对象的共享。
    • JDK8之前,Hotspot中方法区的实现是永久代,JDK7开始把原本放在永久代的字符串常量池、静态变量等移出到堆,JDK 8 开始去除永久代,使用元空间(Metaspace),永久代剩余内容移至元空间,元空间直接在本地内存分配。
  • 直接内存:直接内存并不属于Java规范规定的属于Java虚拟机运行时数据区的一部分。Java的NIO可以使用Native方法直接在java堆外分配内存,使用DirectByteBuffer对象作为这个堆外内存的引用。

堆和栈的比较

  • 堆主要存放对象,栈主要执行程序
  • 堆可以动态分配内存,生存期不受编译器控制,灵活性好,但存取速度慢
  • 栈中数据大小与生存期有关,缺乏灵活性

一文搞懂JVM内存结构!真的写的好!

怎么判断一个对象是否能被回收——GC Roots

垃圾的定义

内存中不再被使用的空间就是垃圾

怎么判断一个对象是否能被回收
 程序计数器、虚拟机栈、本地方法栈。这几个区域完全不用管回收问题,因为方法结束或者线程结束的时候他们所占用的内存就自然跟着一起释放了,3个区域随线程而生,随线程而灭。所以我们只需要管堆和方法区。

  • 引用计数法:通过给对象添加计数器,每当有一个地方引用它,计数器值就 + 1,有一个地方引用失效就,计数器值就 - 1。只要计数器值为零,就说明这个对象不再被使用,可以当作垃圾回收。
    • 优缺点:实现简单。引用计数器本身需要维护,也会有一定损耗。解决不了循环引用的问题。
  • 每局根节点(GC Roots)做可达性分析(根搜索路径):以”GC Roots(Tracing Root)“的对象作为起始点,向下搜索,如果一个对象到GC Roots没有任何引用链相连时,则说明此对象不可用。
  • 可作为GC Root的对象:
    • 虚拟机栈中引用的对象
    • 方法区中类静态属性引用的对象
    • 方法区中常量引用的对象
    • 本地方法栈中JNI(native方法)中引用的对象

JVM之GC Roots概述

垃圾回收机制

jvm内存结构:分为年轻代和老年代。年轻代又分为Eden和survivor区(又分为from和to两个区)。Eden:from:to=8:1:1。

  • 新生代对象在Eden区产生且优先分配在Eden区。当Eden没有足够空间时,将发生Minor GC。
  • 当Eden区满了或放不下了,这时候其中存活的对象会复制到from区。(如果存活下来的对象from区都放不下,则这些存活下来的对象全部进入老年代。之后Eden区的内存全部回收掉。
  • 之后产生的对象继续分配在Eden区,当Eden区又满了或放不下了,这时候将会把Eden区和from区存活下来的对象复制到to区。(如果存活下来的对象to区都放不下,则这些存活下来的对象全部进入年老代,之后回收掉Eden区和from区的所有内存(此时from区是空的,然后将from区和to区交换,即保持to区为空, 如此往复。)。
  • 会有很多对象会被复制很多次(每复制一次,对象的年龄就+1),默认情况下,当对象被复制了15次(这个次数可以通过:-XX:MaxTenuringThreshold来配置),就会进入年老代了。
  • 当年老代满了或者存放不下将要进入年老代的存活对象的时候,就会发生一次Full GC(这个是我们最需要减少的,因为耗时很严重)。

什么时候开始回收

GC并不是等变量为空就回收内存,而是超出变量的作用域后就会被自动回收。

垃圾收集器

串行收集器

使用单线程进行垃圾回收的收集器,每次回收时,串行收集器只有一个工作线程,对于并行能力较弱的计算机来说,串行收集器的专注性和独占性往往有更好的性能表现。串行收集器可以在新生代和老年代中使用,根据作用于不同的堆空间,分为新生代串行收集器和老年代收集器。

  • Serial收集器:新生代串行收集器,使用复制算法。它在进行垃圾收集时,必须暂停其他所有的工作线程,是JVM client模式下默认的新生代收集器。Serial收集器没有线程交互的开销,专心做垃圾收集可以获得最高的单线程收集效率。
  • Serial Old收集器 :Serial收集器的老年代版本,使用标记-整理算法。给Client模式下的虚拟机使用,如果在Server模式下
    • 一、在JDK1.5以及之前的版本中与Parallel Scavenge收集器搭配使用
    • 二、作为CMS收集器的后备预案,在并发收集发送Concurrent Mode Failure时使用。

并行收集器

  • ParNew收集器:Serial收集器的多线程版本
  • Parallel Scavenge收集器:新生代使用并行回收收集器,老年代使用串行收集器
    • 吞吐量优先收集器,目标是达到一个可控制的吞吐量(Throughput)。
  • Parallel Old收集器:新生代和老年代都使用并行回收收集器
    • Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。
  • CMS收集器:以获取最短回收停顿时间为目标的收集器。
    • 非常符合互联网站或者B/S系统的服务端上,重视服务的响应速度,希望系统停顿时间最短的应用
    • 基于“标记—清除”算法实现的
    • CMS收集器的内存回收过程是与用户线程一起并发执行的
    • 初始标记:标记GC Roots能直接关联到的对象,速度很快
    • 并发标记:进行GC Roots Tracing的过程
    • 重新标记:为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,但远比并发标记的时间短
    • 并发清除
    • 优点:并发收集、低停顿
    • 缺点:对CPU资源非常敏感、无法处理浮动垃圾,可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生。一款基于“标记—清除”算法实现的收集器
  • G1(Garbage-First)收集器:当今收集器技术发展的最前沿成果之一,G1是一款面向服务端应用的垃圾收集器。
    • 优点:并行与并发:充分利用多CPU、多核环境下的硬件优势
    • 分代收集:不需要其他收集器配合就能独立管理整个GC堆
    • 空间整合:“标记—整理”算法实现的收集器,局部上基于“复制”算法不会产生内存空间碎片
    • 可预测的停顿:能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒
    • 步骤:初始标记:标记一下GC Roots能直接关联到的对象,需要停顿线程,但耗时很短
    • 并发标记:是从GC Root开始对堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,但可与用户程序并发执行
    • 最终标记:修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录
    • 筛选回收:对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划

参考

Minor GC、Major GC和Full GC

  • Minor GC:对新生代进行回收,不会影响到年老代。因为新生代的 Java 对象大多死亡频繁,所以 Minor GC 非常频繁,一般在这里使用速度快、效率高的算法,使垃圾回收能尽快完成。
  • Major GC:清理老年代。发生 Major GC 一定会发生一次Minor GC
  • Full GC:对整个堆进行回收,包括新生代和老年代。由于Full GC需要对整个堆进行回收,所以比Minor GC要慢,因此应该尽可能减少Full GC的次数,导致Full GC的原因包括:老年代被写满、永久代(Perm)被写满和System.gc()被显式调用等。

四种垃圾回收算法——分代收集算法

  • 标记清除:从根集合节点开始先标记所有存活对象,然后清除所有未被标记的对象
    • 适用于:存活对象较多的情况,适用于老年代(旧生代)
    • 缺点:容易产生生存碎片,(来一个新的对象比所有空闲表都大),这样容易提前触发垃圾回收。扫描了整个空间两次(一次标记,一次清除)
  • 复制算法:从根集合节点进行扫描,标记出所有的存活对象,并将这些存活的对象复制到一块儿新的内存上去,之后将原来的那一块儿内存全部回收掉。
    • 适用于:存活对象较少的情况。使用与年轻代(新生代)。只扫描了整个空间一次。
    • 缺点:需要额外的一块空的内存空间。需要复制移动对象。
  • 标记整理:从根节点开始对存活对象进行标记,并将所有存活对象压缩到内存的一段,清理边界所有空间。
    • 优点:避免了碎片的产生,不需要两块相同的内存空间,性价比比较高。
  • 分代收集算法:不同年代使用不同的算法。新生代存活率低,使用复制算法,老年代对象存活率高,使用标记清除或标记整理。

垃圾回收算法——分代收集算法

GC算法优劣标准

  • 吞吐量越高算法越好
    JVM在专门的线程[GC Threads]中执行GC 只要GC线程是活动的 就会和应用程序线程[Application Threads]争用当前可用CPU的时钟周期而吞吐量就是指应用程序线程占程序总用时的比例
    吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间),虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%。
  • 暂停时间越短算法越好
    一个时间段内应用程序线程让GC线程执行而完全暂停。这样可以终止所有应用线程,不会产生新的垃圾,并且保证了系统状态在某一瞬间的一致性,有益于更好的标记垃圾对象。

双亲委派机制

JVM在加载类时默认采用的是双亲委派机制。通俗的讲,就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
在这里插入图片描述
注意:

  • 类加载器代码本身也是java类,因此类加载器本身也是要被加载的,因此显然必须有第一个类加载器不是Java类,这就是bootStrap,是使用c++写的其他这是java了。
  • 虽说bootStrap、extclassLoader、appclassloader三个是父子类加载器关系,但是并没有使用继承,而是使用了组合关系
  • 优点
    • 保证程序安全,防止核心API被随意篡改:具备了一种带优先级的层次关系,越是基础的类,越是被上层的类加载器进行加载,可以比较笼统的说像jdk自带的几个jar包肯定是位于最顶级的,再就是我们引用的包,最后是我们自己写的,保证了java程序的稳定性。
    • 避免类的重复加载

谈谈双亲委派

沙箱机制

我们创建一个自定义string类,但是在加载自定义String类的时候会率先使用引导类加载器加载,而引导类加载器在加载的过程中会先加载jdk自带的文件(rt.jar包中java\lang\String.class),报错信息说没有main方法,就是因为加载的是rt.jar包中的string类。这样可以保证对java核心源代码的保护,这就是沙箱安全机制。

打破双亲委派机制

Tomcat打破双亲委派机制

引用的分类

  • 强引用:必不可少,不会被垃圾回收器回收的对象
  • 软引用:有用但不必需,只有在JVM内存不足时才被回收
  • 弱引用:非必需对象,一旦被发现就会被回收(但不一定立马被发现)
  • 虚引用:相当于没有引用,任何时候都无法通过引用取到对象值

强引用、软引用、弱引用、虚引用

OOM

谈谈对OOM的认识

深入分析编译原理

深入分析编译原理

逃逸分析

逃逸分析

通过一个类的全限定名获得此类的统一资源定位符

通过一个类的全限定名获得此类的统一资源定位符

类加载器、双亲委派机制、java类加载的沙箱安全机制

热门文章

暂无图片
编程学习 ·

C语言二分查找详解

二分查找是一种知名度很高的查找算法,在对有序数列进行查找时效率远高于传统的顺序查找。 下面这张动图对比了二者的效率差距。 二分查找的基本思想就是通过把目标数和当前数列的中间数进行比较,从而确定目标数是在中间数的左边还是右边,将查…
暂无图片
编程学习 ·

GMX 命令分类列表

建模和计算操作命令: 1.1 . 创建拓扑与坐标文件 gmx editconf - 编辑模拟盒子以及写入子组(subgroups) gmx protonate - 结构质子化 gmx x2top - 根据坐标生成原始拓扑文件 gmx solvate - 体系溶剂化 gmx insert-molecules - 将分子插入已有空位 gmx genconf - 增加…
暂无图片
编程学习 ·

一文高效回顾研究生课程《数值分析》重点

数值分析这门课的本质就是用离散的已知点去估计整体,就是由黑盒子产生的结果去估计这个黑盒子。在数学里这个黑盒子就是一个函数嘛,这门课会介绍许多方法去利用离散点最大化地逼近这个函数,甚至它的导数、积分,甚至微分方程的解。…
暂无图片
编程学习 ·

在职阿里5年,一个28岁女软测工程师的心声

简单的先说一下,坐标杭州,14届本科毕业,算上年前在阿里巴巴的面试,一共有面试了有6家公司(因为不想请假,因此只是每个晚上去其他公司面试,所以面试的公司比较少) ​ 编辑切换为居中…
暂无图片
编程学习 ·

字符串左旋c语言

目录 题目: 解题思路: 第一步: 第二步: 第三步: 总代码: 题目: 实现一个函数,可以左旋字符串中的k个字符。 例如: ABCD左旋一个字符得到BCDA ABCD左旋两个字符…
暂无图片
编程学习 ·

设计模式--观察者模式笔记

模式的定义与特点 观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式&#xf…
暂无图片
编程学习 ·

睡觉突然身体动不了,什么是睡眠痽痪症

很多朋友可能有这样的体验,睡觉过程中突然意识清醒,身体却动弹不了。这时候感觉非常恐怖,希望旁边有一个人推自己一下。阳光以前也经常会碰到这样的情况,一年有一百多次,那时候很害怕晚上到来,睡觉了就会出…
暂无图片
编程学习 ·

深入理解C++智能指针——浅析MSVC源码

文章目录unique_ptrshared_ptr 与 weak_ptrstd::bad_weak_ptr 异常std::enable_shared_from_thisunique_ptr unique_ptr 是一个只移型别(move-only type,只移型别还有std::mutex等)。 结合一下工厂模式,看看其基本用法&#xff…
暂无图片
编程学习 ·

@TableField(exist = false)

TableField(exist false) //申明此字段不在数据库存在,但代码中需要用到它,通知Mybatis-plus在做写库操作是忽略它。,.
暂无图片
编程学习 ·

Java Web day15

第十二章文件上传和下载 一、如何实现文件上传 要实现Web开发中的文件上传功能,通常需要完成两步操作:一.是在Web页面中添加上传输入项;二是在Servlet中读取上传文件的数据,并保存到本地硬盘中。 需要使用一个Apache组织提供一个…
暂无图片
编程学习 ·

【51nod 2478】【单调栈】【前缀和】小b接水

小b接水题目解题思路Code51nod 2478 小b接水 题目 输入样例 12 0 1 0 2 1 0 1 3 2 1 2 1输出样例 6解题思路 可以发现最后能拦住水的都是向两边递减高度(?) 不管两个高积木之间的的积木是怎样乱七八糟的高度,最后能用来装水的…
暂无图片
编程学习 ·

花了大半天写了一个UVC扩展单元调试工具

基于DIRECTSHOW 实现的,用的是MFC VS2019. 详见:http://www.usbzh.com/article/detail-761.html 获取方法 加QQ群:952873936,然后在群文件\USB调试工具&测试软件\UVCXU-V1.0(UVC扩展单元调试工具-USB中文网官方版).exe USB中文网 USB中文…
暂无图片
编程学习 ·

贪心(一):区间问题、Huffman树

区间问题 例题一:区间选点 给定 N 个闭区间 [ai,bi]请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。 输出选择的点的最小数量。 位于区间端点上的点也算作区间内。 输入格式 第一行包含整数 N,表示区间数。 接下来 …
暂无图片
编程学习 ·

C语言练习实例——费氏数列

目录 题目 解法 输出结果 题目 Fibonacci为1200年代的欧洲数学家,在他的着作中曾经提到:「若有一只免子每个月生一只小免子,一个月后小免子也开始生产。起初只有一只免子,一个月后就有两只免子,二个月后有三只免子…
暂无图片
编程学习 ·

Android开发(2): Android 资源

个人笔记整理 Android 资源 Android中的资源,一般分为两类: 系统内置资源:Android SDK中所提供的已经定义好的资源,用户可以直接拿来使用。 用户自定义资源:用户自己定义或引入的,只适用于当前应用的资源…
暂无图片
编程学习 ·

零基础如何在短时间内拿到算法offer

​算法工程师是利用算法处理事物的职业 算法(Algorithm)是一系列解决问题的清晰指令,也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。 如果一个算法有缺陷,或不适合于某个问题,执…
暂无图片
编程学习 ·

人工智能:知识图谱实战总结

人工智能python,NLP,知识图谱,机器学习,深度学习人工智能:知识图谱实战前言一、实体建模工具Protegepython,NLP,知识图谱,机器学习,深度学习 人工智能:知识图…
暂无图片
编程学习 ·

【无标题】

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…