【JavaSE】简单理解JVM

【JavaSE】简单理解JVM

目录

一、JVM内存区域划分

JVM:java虚拟机,是仿照真实的操作系统进行设计的。真实操作系统中,对于进程的地址空间是进行了区域划分的。JVM也就仿照此,也进行了区域划分的设计。

具体划分(四个核心区域):

  1. 程序计数器:一个很小的区域,只用来记录当前指令执行到哪个地址。
  2. 元数据区:保存当前类被加载好的数据(类对象 .class),Java8之前叫方法区。
  3. 栈:保存方法的调用关系。
  4. 堆:保存 new 的对象。这句代码:Test t = new Test() 代码中new Test()一定在堆中,t 是局部变量就在栈;t 是成员变量就在堆; t 是一个静态成员变量就在元数据区。

二、类加载机制

2.1 类加载的步骤

类加载的步骤:

  1. 加载:找到 .class 文件 ,根据类的全限定名(包名+类名),打开文件,读取文件内容读到内存中;
  2. 连接:
    2.1. 验证:解析,校验 .class文件的内容是否合法,并把合法内容转成结构化的数据
    2.2. 准备:给类对象申请内存空间(此处相当于全0的空间);
    2.3. 解析:针对字符串常量,进行初始化;(将 .class文件解析出的字符串常量,放到元数据区,常量池中);
  3. 初始化:将类对象进行初始化。

2.2 双亲委派模型

双亲委派模型:描述类加载中,根据全限定类名,找到.class 文件的过程。

类加载器:JVM中专门的模块,负责类加载。JVM默认提供三种类加载器(存在父子关系,1是爷,2是爸,3室儿):

  1. BootstrapClassLoader:找Java标准库的目录
  2. ExtensionClassLoader:找Java扩展库的目录
  3. ApplicationClassLoader:第三方库和当前项目的目录

过程:

  • 进行类加载的时候,通过全限定类名找.class文件时,先从ApplicationClassLoader作为入口,然后把加载类的任务交给父亲 ExtensionClassLoader,他又先给他的父亲 BootstrapClassLoader,然后 BootstrapClassLoader找Java标准库范围,找到了就加载,没找到就抛回给儿子 ExtensionClassLoader,同理进行。最后 ApplicationClassLoader都没找到,就抛出异常。

三、垃圾回收机制 (GC)

Java中释放内存(主要是针对堆上的对象)的手段。
在c语言中手动申请的内存需要手动释放,而Java引入GC会自动识别,某个内存后续是否还会使用,自动释放。

工作过程:

  1. 找到垃圾
  2. 释放垃圾

找到垃圾:
有两个方案,引用计数和可达性分析,Java采取的是可达性分析。

  1. 引用计数:给每一个对象在new的时候,搭配上一个小的内存空间,保存一个整数,表示指向这个对象的引用个数。
    1.1. 每次进行引用赋值的时候都会触发引用计数的修改,当计数为0的时候,这个对象就是垃圾了。
    1.2. 缺陷:内存消耗更多,可能出现循环引用(两个对象互相引用,引用变空,但是计数不会变为0)的问题。
  2. 可达性分析:用时间换空间,是一个周期性的过程,每隔一段时间,触发一次。
    2.1. 以代码中的一些特定对象(栈上的局部变量(引用类型的)、常量池引用指向的对象、静态成员(引用类型)),作为遍历的起点。
    2.2. 以这些特殊对象为起点,尽可能去遍历,判断某个对象是否能访问到。
    2.3. 每一次访问到一个对象,就把这个对象标记成可达,当完成所有的对象,未被标记的就是垃圾。

释放垃圾:

  • 标记 - 清除:把垃圾对象的内存直接进行释放。
    • 缺点:会产生内存碎片问题(回收后导致内存空间不连续)
  • 复制算法:一片内存空间,一分为二,一次只使用其中一半。当垃圾回收的时候,先将不是垃圾的内存复制到另一半没使用的内存中,再将这一半整体释放掉。
    • 缺点:内存空间利用率低,一旦不是垃圾的对象很大,复制的成本就很高。
  • 标记 - 整理:类似于顺序表删除数据操作,将不是垃圾的内存向前移动,最后回收后面一片的内存。
    • 缺点:内存搬运数据的成本很高。
  • 分代回收:把上面的三种方式结合起来,主要是2和3。Java给的策略。
    • ”代” - 》指代对象经历的GC轮次(先将内存分为 新生代区 和 老年代区),初始为0,经一轮GC后就加1;如果一个对象的轮次已经很大了,那么大概率还会存在很久。对轮次大的对象,GC的频率就会降低。
    • 进一步会将新生代分为 伊甸区 和两个幸存区,比例大概8:1:1。
    • 新创建的对象放入伊甸区,大部分伊甸区的对象熬不过第一轮GC,熬过去了就通过 复制算法 进入一个幸存区;
    • 一个幸存区的对象又熬过一轮GC就会通过 复制算法 进入另一个幸存区,反复跳跃
    • 如果一个对象在幸存区经历了多轮GC,就会晋升到老年代区。
    • 老年代区就使用的标记 - 整理 回收机制。
    • 如果一个对象特别大,直接进入老年代区。

Read more

【强化学习】深度确定性策略梯度算法(DDPG)详解(附代码)

【强化学习】深度确定性策略梯度算法(DDPG)详解(附代码)

📢本篇文章是博主强化学习(RL)领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在👉强化学习专栏:        【强化学习】- 【单智能体强化学习】(10)---《深度确定性策略梯度算法(DDPG)详解》 深度确定性策略梯度算法(DDPG)详解 目录 DDPG算法详细介绍 算法特点 核心改进点 算法公式推导 1. Q值函数更新 2. 策略更新(Actor网络) 3. 目标网络更新 算法流程 [Python] DDPG算法实现 1. 导入必要库 2. 定义 Actor 网络 3. 定义 Critic 网络 4. 定义经验回放池 5.

By Ne0inhk
【数据结构与算法】解锁顺序表潜能:一站式实现高效通讯录系统

【数据结构与算法】解锁顺序表潜能:一站式实现高效通讯录系统

🔥小龙报:个人主页 🎬作者简介:C++研发,嵌入式,机器人等方向学习者 ❄️个人专栏:《C语言》《【初阶】数据结构与算法》 ✨ 永远相信美好的事情即将发生 文章目录 * 前言 * 一、通讯录框架Test.c * 二、通讯录 * 2.1 Contacts.h * 2.2 Contacts.c * 三、底层逻辑 * 3.1 SeqList.h * 3.2 SeqList.c * 四、基于顺序表的通讯录实现效果 * 4.1 添加 * 4.2 删除 * 4.3 修改 * 4.4

By Ne0inhk
《数据结构风云》递归算法:二叉树遍历的精髓实现

《数据结构风云》递归算法:二叉树遍历的精髓实现

🔥@晨非辰Tong: 个人主页 👀专栏:《C语言》、《数据结构与算法入门指南》 💪学习阶段:C语言、数据结构与算法初学者 ⏳“人理解迭代,神理解递归。” 文章目录 * 引言 * 一、单值二叉树 * `1.目标特征描述:什么单值二叉树` * `2.目标实现示例:` * `3.算法思路:` * `3.1 具体代码实现` * 二、相同的树 * `1.目标特征描述:什么是相同的树` * `2.目标实现示例` * `3.算法思路` * `3.1 具体代码实现` * 三、另一棵树的子树 * `1.目标特征描述` * `2.目标实现示例` * `3.算法思路` * `3.1 具体代码实现` * 四、对称二叉树 * `1.

By Ne0inhk
无中生有——无监督学习的原理、算法与结构发现

无中生有——无监督学习的原理、算法与结构发现

“世界上绝大多数数据都没有标签。 真正的智能,不是在已知答案中选择,而是在混沌中发现秩序。” ——无监督学习的哲学 一、为什么需要无监督学习? 在前七章中,我们系统学习了监督学习(Supervised Learning)的核心范式:给定输入 x\mathbf{x}x 和对应标签 yyy,学习映射 f:x↦yf: \mathbf{x} \mapsto yf:x↦y。无论是线性回归、决策树,还是神经网络,都依赖于标注数据这一稀缺资源。 然而,现实世界的数据绝大多数是未标注的: * 用户浏览日志(只有行为,没有“好/坏”标签); * 医学影像(只有图像,没有诊断结论); * 社交网络(只有连接关系,没有群体划分); * 传感器时序(只有数值流,没有异常标记)

By Ne0inhk