【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

TRAE、VSCode上进行git管理

最近在学习Node.js,但是对TRAE/VSCode的git操作有点不太会,因此记录一下,如有不对,请指出。 我这里使用的是TRAE演示,VSCode应该差不多。 首先是从github,或者gitee上将项目clone下来。看图操作 此时会在页面最上方显示一个弹窗,输入你的项目地址 选择你的项目存放路径 稍等片刻后,项目就clone到你本地了。 使用TRAE/VSCode打开项目。 一般项目会有很多分支,比如主分支,上线版本分支,需求分支,开发分支,咱们举个例子: 主分支:main(作为所有分支的主分支,会合并所有没有bug的代码) 版本分支:release_projectName_versionCode_date(一般用来归档项目版本节点,如果后期某个版本有线上Bug,就基于这个分支修改) 需求分支:feature_projectName_versionCode_main_date(一般有新需求了,就会新建这个分支) 开发分支:feature_projectName_versionCode_userName_

By Ne0inhk
Python实现开源AI模型引入及测试全过程

Python实现开源AI模型引入及测试全过程

文章目录 * 摘要 * 1. 引言:开源AI生态系统概述 * 1.1 开源AI的发展现状 * 1.2 技术栈选择 * 1.3 项目目标 * 2. 环境配置与项目初始化 * 2.1 系统要求 * 2.2 创建虚拟环境 * 2.3 依赖管理文件 * 2.4 安装依赖 * 2.5 项目结构 * 3. 模型原理与架构解析 * 3.1 BERT模型原理 * 3.1.1 Transformer编码器架构 * 3.2 Hugging Face Transformers架构 * 4. 数据准备与预处理 * 4.1 数据集选择与加载

By Ne0inhk
剖析 SOFATracer:蚂蚁金服开源分布式链路追踪组件

剖析 SOFATracer:蚂蚁金服开源分布式链路追踪组件

目录 一、为什么需要 SOFATracer?  二、核心思想与能力 (一)基于 OpenTracing 标准构建 1. OpenTracing 标准 2. SOFATracer 如何实现标准? a. Tracer 接口实现(SofaTracer) b. Span 实现(SofaTracerSpan) c. SpanContext 透传(SofaTracerSpanContext) 3. 标准机制带来的优势 4. 与分布式追踪基础论文的联系 5. 传播机制与链路构建过程 (二)全局 TraceId + SpanId 串联链路 (三)高性能日志异步写盘 1. 问题背景:为什么同步写日志是灾难? 1.1 I/O 阻塞放大 RT

By Ne0inhk