JVM学习笔记

JVM学习笔记

复习之前学的内容,同时补充以下知识点:JVM的双亲委派机制、伊甸区与老年代相关知识;
在这里插入图片描述

双亲委派机制

双亲的含义应该就是AppClassLoader有:ExtClassLoader和BootstrapClassLoader“两个”父加载器。
首先介绍Java中的类加载器

Java中的类加载器

Bootstrap ClassLoader(启动类加载器),默认加载jdk\lib目录下jar中的诸多类。可以使用-Xbootclasspath指定。
Extension ClassLoader(扩展类加载器),默认加载jdk\lib\ext目录下的jar中的诸多类。可以使用java.ext.dirs系统变量更改。
Application ClassLoader(应用程序加载器),应用程序加载器,负责加载开发人员所编写的诸多类。
User ClassLoader(自定义加载器),自定义类加载器,当存在上述加载器解决不了的特殊情况时,或者存在特殊要求时,可以自行实现类加载逻辑。
关系图:
在这里插入图片描述

双亲委派

通俗故事:

  1. 假设用户刚刚摸鱼时写了个Test类想进行加载,此时会发送给应用程序类加载器AppClassLoader;
  2. 然后AppClassLoader并不会直接去加载Test类,而是会委派于父类ExtClassLoader,来完成此操作;
  3. ExtClassLoader同样不会直接加载Test类,而是会继续委派父类BootstrapClassLoader;
  4. BootstrapClassLoader已经是顶层了,没有更高的父类加载器了,因此BootstrapClassLoader就从jdk\lib中搜索是否存在,因为这里是用户自己写的Test类,因此不会存在于jdk下,所以此时会给子类一个反馈;
  5. ExtClassLoader收到父类传回的反馈,知道父类加载器没有找到对应的类,爸爸靠不住,就只能自己来加载了,结果显而易见,自己也不行,只能给下面的子类加载器,AppClassLoader;
  6. AppClassLoader收到父类加载器的反馈,顿时明白,原来爸爸虽然是爸爸,但是终究不能管儿子的私事,所以此时,AppClassLoader就自己尝试去加载。
  7. 结果,就这样成功了,走了一大圈,兜兜转转还是自己干。
什么是双亲委派
为什么使用双亲委派

专业性解释:①避免类的重复加载;②防止核心API被篡改;
为了避免原始类被覆盖的问题。
老子走过的路,小子不用走
比如,用户编写了一个Object类,放入程序中加载。
当没有双亲委派机制时,就会出现重复的Object类,给开发人员造成很大的困扰,本来就只需要基于JDK开发就好了,现在还得把JDK中的类全记住,避免编写重复的类。
当存在双亲委派机制时,整个事情就不一样了,每次加载类时,都会遵循双亲委派机制,去问父类是否可以加载,如果可以呢,那就不需要再次加载了,这样事情就简单了。

Tomcat为什么要自定义类加载器

在这里插入图片描述

如何打破双亲委派模型(太高级,尝试看一下)

为什么要考虑这个问题?

  1. 自定义类加载器时,重写loadClass方法。
双亲委派还有什么

运行时数据区

在这里插入图片描述
蓝色部分是多个线程共享部分;
绿色部分为单个线程独享部分;

方法区

解释器
JIT编译器
GC
为什么需要GC

垃圾是指JVM中没有任何引用指向的对象,如果不清理这些垃圾对象,那么他们就一直占用内存,而不能给其他对象使用,最终垃圾对象越来越多,就会出现OOM。

垃圾标记阶段

先找到垃圾对象。

引用计数法:

每个对象保存一个引用计数器属性,用户记录对象被引用的次数。
a)优点:实现简单,计数器为0就是垃圾对象;
b)缺点:
①无法解决循环引用问题;
②需要额外的空间记录;
③需要额外的时间维护应用计数。
在这里插入图片描述

可达性分析方法:

以GCRoots作为起始点,然后一层一层找到对应的对象,被找到的对象就是存活对象,那么其他对象就是不可达对象,即垃圾对象。
GCRoots包括:

  1. 线程中虚拟机栈中正在执行的方法中方法参数、局部变量所对应的对象引用;
  2. 线程中本地方法栈中正在执行的方法中方法参数、局部变量所对应的对象引用;
  3. 方法区保存的类对象的静态属性所对应的对象引用;
  4. 方法区保存的类对象的常量属性所对应的对象引用;
  5. 等等;
标记清除算法

STW,Stop The World;

  1. 标记阶段:
  2. 清除阶段:

a) 缺点:效率不高;产生内存碎片;
b) 优点:逻辑简单;

复制算法

Copying
将内存分为两块,每次只使用其中一块,进行GC时,将可达对象赋值到另外没有被使用的内存块中,然后再清楚当前内存块中的所有对象,内存块交替使用。
a) 缺点:耗费空间较大;可达对象多时,效率很低,因此适用于新生代,垃圾对象多的空间;对象内存之地变化之后,需要额外的时间修改对象的引用地址。
b) 优点:没有内存碎片;没有标记和清除阶段,直接复制操作,不需要修改对象头

标记-整理算法

Mark-Compact算法
第一阶段,从GCRoots找到并标记可达对象;
第二阶段,将所有存活对象移动到内存的一端;
最后清理边界外所有的空间;
a) 缺点:需要修改对象引用地址;适用于垃圾对象少、可达对象多;效率低 ,三种当中最低的;
b) 优点:没有内存碎片;不需要额外的内存空间;

分代收集算法

分代收集的理念
不同对象的存活时间不一样,因此可以针对不同的对象采取不同的垃圾回收算法。

  • 新生代的对象存活时间比较短,那么就可以利用复制算法,它适合对象比较多的情况。
  • 老年代的对象存活时间比较长,所以不适合用复制算法,可以用标记-清除或者标记-整理算法,比如:
    a) CMS垃圾收集器采用的就是标记-清除算法;
    b) Serial Old采用的就是标记-整理算法;
    在这里插入图片描述
CMS垃圾收集器

整个垃圾收集过程变长了,但是STW时间变短了;
在这里插入图片描述

  1. 初始标记;STW
  2. 并发标记;
  3. 重新标记;STW,时间很短;
  4. 并发清理;
  5. 并发重置;
    当出现新对象要进入老年代,但是空间不够时,会导致“concurrent mode failure”,此时可以利用Serial Old进行一次垃圾收集,就是做一次全局STW。
G1垃圾收集器

Garbage First
将整个内存分为一个个的方块,均分为2048块。
在这里插入图片描述

  1. 初始标记;STW;
  2. 并发标记;
  3. 最终标记;STW;
  4. 筛选回收;STW;可以通过-XX:MaxGCPauseMillis来制定GC的STW停顿的时间,所以可能并不会回收掉所有垃圾对象,默认200ms;采用复制算法,不会产生碎片(会把某个region对象复制到另外空闲的region中)
    YoungGC:Eden区满了,就会触发G1的YoungGC,对Eden区进行GC
    MixedGC:老年代占用率达到了-XX:InitiatingHeapOccupancyPercent指定的百分比,回收所有的新生代以及部分老年代,以及大对象区
    FullGC:在进行MixedGC过程中,采用复制算法,如果复制过程内存不够,会触发FullGC,会STW,并采用单线程进行标记-整理算法进行GC,相当于一次Serial GC;

堆区

在这里插入图片描述
所有的对象和数组都应该存放在堆区,在执行字节码指令时,会把创建的对象存入堆中,对象对应的引用地址存入虚拟机栈中的栈帧中,不过当方法执行完之后,刚刚被创建的对象并不会被回收,而是要等JVM后台执行GC之后,对象才会被回收。

  • Xms:设置堆的初始化内存大小,等价于-XX:InitialHeapSize;
  • Xmx:设置堆的最大内存,等价于-XX:MaxHeapSize;
    一般会把两个设置为一样,这样JVM就不需要再GC后去修改堆的内存大小了,提高了效率,默认,初始化内存大小=物理内存大小/64,最大内存大小=物理内存大小/4;
新生代

可以通过-XX:NewRatio参数来配置新生代和老年代的比例,默认是2,新生代占1,老年代占2,也就是新生代占堆区的1/3;
一般不需要调整,只有明确知道存活时间比较长的对象偏多,那么就需要调大NewRatio,从而调整老年代的占比;

  • Eden:伊甸园区,新对象都存放在伊甸区(除非对象的大小超过了Eden区,那么就只能直接进入老年代)
  • S0、S1区:Survivor0、Survivor1区,也可以叫做from区,to区,用来存放MinorGC(YGC)后的对象。
  • 默认情况下(Eden区:S0区:S1区)的比例关系为(8:1:1),即Eden区占8/10;可以用-XX:SurvivorRatio调整。

YGC,Young Garbage Collection,新生代垃圾回收,将Eden区对象放入S0区;S0区和S1区交替使用;

老年代

当达到某个条件之后,剩余对象就会被保存到老年代中。
遇到第二个非常大的对象,Eden区原有一个大对象,内存不够用时,Eden区的大对象会被直接放到老年代(S0、S1区放不下)
或者来了一个超大对象,可以直接放进老年代;

GC分类
  • Young GC/Minor GC:负责对新生代进行垃圾回收
  • Old GC/Major GC:负责对老年代进行垃圾回收,目前只有CMS垃圾收集器会单独对老年代进行垃圾收集,其他垃圾收集器基本都是在整堆回收的时候对老年代进行垃圾收集
  • Full GC:整堆回收,也会堆方法区进行垃圾收集。

程序计数器

记录下一条待执行指令的地址;

  1. 是物理寄存器的抽象实现;
  2. 用来记录下一条待执行指令的地址;
  3. 它是程序控制流的指示器,循环、if else、异常处理、线程恢复等都依赖它来完成;
  4. 解释器工作时就是通过它来获取下一条需要执行的字节码指令的;
  5. 是唯一一个在JVM规范中没有规定任何OutOfMemoryError情况的区域。
    在这里插入图片描述

Java方法栈

虚拟机栈是线程私有的,每个线程创建时都会创建一个虚拟机栈,栈内保存一个栈帧,一个栈帧就对应一个方法。

  1. 虚拟机栈是线程私有的
  2. 一个方法开始执行,栈帧入栈、方法执行完对应的栈帧就出栈,所以虚拟机栈不需要进行垃圾回收
  3. 虚拟机栈存在OutOfMemoryError,和StackOverFlowError;
  4. 线程太多,就会出现OutOfMemoryError,线程创建时没有足够的内存去创建虚拟机栈了;
  5. 方法调用层数过多,就会出现StackOverFlowError;
  6. 可以通过-Xss来设置虚拟机栈的大小。
    在这里插入图片描述
栈帧:

在这里插入图片描述
操作数栈:也可以叫做操作栈,是栈帧的一部分,操作数栈是用来执行字节码指令过程中用来进行计算的。

操作数栈

比如加法过程,运算操作数在计算过程中的进栈出栈;
在这里插入图片描述

局部变量表

保存局部变量,比如加法过程中,其实每个变量的值都是保存在局部变量表中的。

方法返回地址
动态链接

本地方法栈

C/C++语言写的一些代码
存的是本地方法的栈帧,也是线程私有的,也会OOM和SOF。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/92586.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Stm32_标准库_4_TIM中断_PWM波形_呼吸灯

基本原理 PWM相关物理量的求法 呼吸灯代码 #include "stm32f10x.h" // Device header #include "Delay.h"TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_OCInitTypeDef TIM_OCInitStructuer;//结构体 GPIO_InitTypeDef GPIO_InitStructur…

【Git】Git 原理和使用

Git 一、Git 本地仓库1. 本地仓库的创建2. 配置 Git3. 工作区、暂存区、版本库4. 添加文件5. 查看 .git 文件6. 修改文件7. 版本回退8. 撤销修改9. 删除文件 二、分支管理1. 理解分支2. 创建分支3. 切换分支4. 合并分支5. 删除分支6. 合并冲突7. 分支管理策略8. bug 分支9. 强制…

TempleteMethod

TempleteMethod 动机 在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因 (比如框架与应用之间的关系)而无法和任务的整体结构同时实现。如…

Armv8/Armv9 Cache知识大纲分享--思维导图

关键词:cache学习、mmu学习、cache资料、mmu资料、arm资料、armv8资料、armv9资料、 trustzone视频、tee视频、ATF视频、secureboot视频、安全启动视频、selinux视频,cache视频、mmu视频,armv8视频、armv9视频、FF-A视频、密码学视频、RME/CC…

Acwing 838. 堆排序

Acwing 838. 堆排序 题目描述思路讲解代码展示 题目描述 思路讲解 堆是一颗完全二叉树,除了最下面一层,其余是满的,最后一层从左到右排列 小根堆:每个点小于等于左右两堆,所以根节点就是最小值 大根堆:每个…

Docker Tutorial

什么是Docker 为每个应用提供完全隔离的运行环境 Dockerfile, Image,Container Image: 相当于虚拟机的快照(snapshot)里面包含了我们需要部署的应用程序以及替它所关联的所有库。通过image,我们可以创建很…

美容店预约小程序搭建流程

随着科技的不断发展,小程序已经成为了人们生活中不可或缺的一部分。对于美容店来说,搭建一个预约小程序不仅可以提高工作效率,还可以增加客户数量、提高服务质量。那么,如何搭建一个美容店预约小程序呢?本文将为你详细…

git使用,一点点

查看自己有没有安装git git --version 如果没有安装请执行sudo yum install -y git来安装 git 指令 git log 查看日志 git pull 同步远端和本地仓库 这就是冲突的报错: 所以这个时候你要同步一下git pull

【项目实战】单数据源多数据库实现多租户

文章目录 前言多租户的四种实现方案单数据源多数据库实现思路代码实现 总结 前言 多租户(Multi-Tenancy)是一种软件架构设计模式,旨在使单个应用程序可以同时为多个租户(如不同组织、用户或客户)提供服务,…

CSS 相关

CSS 相关 CSS布局如何管理CSS 代码目录?分多个目录的话,会有命名冲突,那如何解决命名冲突? box-sizing:border-boximage的宽度的问题: CSS布局 单列布局:将一个元素作为布局容器。通常设置一个较小的宽度(最…

MATLAB中d2d函数用法

目录 语法 说明 示例 重新采样离散时间模型 重新采样已识别的离散时间模型 d2d函数的功能是重新采样离散时间模型。 语法 sys1 d2d(sys, Ts) sys1 d2d(sys, Ts, method) sys1 d2d(sys, Ts, opts) 说明 sys1 d2d(sys, Ts)将离散时间动态系统模型 sys 重新采样&#…

JAVA 异常分类及处理

1 概念 如果某个方法不能按照正常的途径完成任务,就可以通过另一种路径退出方法。在这种情况下会抛出一个封装了错误信息的对象。此时,这个方法会立刻退出同时不返回任何值。另外,调用 这个方法的其他代码也无法继续执行,异常处理…

OCI 发布了容器运行时和镜像规范!

7 月 19 日是开放容器计划Open Container Initiative(OCI)的一个重要里程碑,OCI 发布了容器运行时和镜像规范的 1.0 版本,而 Docker 在这过去两年中一直充当着推动和引领的核心角色。 我们的目标是为社区、客户以及更广泛的容器行…

重试机制-spring-retry、guava-retry

重试机制是什么? 网络重试机制是用于在网络通信中处理失败的请求。接口重试可以在一定的时间间隔内多次尝试发送相同的请求,直到请求成功或达到最大重试次数为止。 为什么要重试? 1. 提高请求的成功率:网络通信中可能会出现各种…

通过 Azure 日志分析加强云安全

Microsoft Azure 云服务在安全日志存储、访问、可伸缩性、降低成本和易于部署方面提供了巨大的优势,因此在企业中很受欢迎。 Microsoft Azure 日志记录工具(如 Log360)可帮助管理 Azure 云基础结构中所有设备和应用程序(如虚拟机…

一点C知识:数据类型和内存地址。

当你需要存储一份数据到内存里的时候,你需要通过需要存储的方式和精度,向操作系统申请一份内存地址,形容怎么样申请地址的关键字就是数据类型。 例如,32位的处理器就有着32位的地址位宽,定义了一个char类型的数据&…

Flutter笔记:AnimationMean、AnimationMax 和 AnimationMin 三个类的用法

Flutter笔记 AnimationMean、AnimationMax 和 AnimationMin三个类的用法 作者:李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 :291148484163.com 本文地址:https://blog.csdn.net/qq_28550263/…

Python绘图系统24:添加辅助坐标轴

文章目录 辅助坐标增减坐标轴时间轴**代码优化源代码 Python绘图系统: 前置源码: Python打造动态绘图系统📈一 三维绘图系统 📈二 多图绘制系统📈三 坐 标 轴 定 制📈四 定制绘图风格 📈五 数据…

MySQL单表查询与多表查询

目录 一、单表查询 ​编辑 1、显示所有职工的基本信息。 ​编辑2、查询所有职工所属部门的部门号,不显示重复的部门号。 ​编辑3、求出所有职工的人数。 4、列出最高工和最低工资。 ​编辑5、列出职工的平均工资和总工资。 ​编辑6、创建一个只有职…

opencv实现目标跟踪及视频转存

创建跟踪器 def createTypeTracker(trackerType): 读取视频第一帧,选择跟踪的目标 读第一帧。 ok, frame video.read() 选择边界框 bbox cv2.selectROI(frame, False) 初始化跟踪器 tracker_type ‘MIL’ tracker createTypeTracker(tracker_type) 用第一…