JVM-内存区域、垃圾回收与类加载机制

目录

[1.JVM 简介](#1.JVM 简介)

​编辑

[2、JVM 运⾏时数据区](#2、JVM 运⾏时数据区)

1、程序计数器(线程私有)

2、元数据区(线程共享)

3、Java虚拟机栈(线程私有)

4、堆(线程共享)

3、JVM类加载

1、类加载步骤有哪些

2、类加载的双亲委派模型是

4、GC垃圾回收

1、找到垃圾(不再使用的对象)

2、释放垃圾(对于的内存释放)

1、标记清理,

2、复制算法

3、标记-整理

4JVM采用分代回收


1.JVM 简介

JVM 是 Java Virtual Machine 的简称,意为 Java虚拟机。 虚拟机是指通过软件模拟的具有完整硬件功能的、运⾏在⼀个完全隔离的环境中的完整计算机系统。 常⻅的虚拟机:JVM、VMwave、Virtual Box。

其实是仿照一个真实的机器或操作系统,操作系统里对进程地址空间进行了划分区域,因此jvm也进行了内存划分

2、JVM 运⾏时数据区

JVM 运⾏时数据区域也叫内存布局,但需要注意的是它和 Java 内存模型((Java Memory Model,简 称 JMM)完全不同,属于完全不同的两个概念,它由以下 5 ⼤部分组成:

1、程序计数器(线程私有)

记录当前指令执行到哪个地址

2、元数据区(线程共享)

保存当前类加载好的数据,.java=>.class=>加载到内存中,运行这个代码就需要把.class加载到内存里面即后面说的类加载机制

3、Java虚拟机栈(线程私有)

保存方法调用的关系,写代码会有方法调用,每次调用方法就会进入到方法内部执行,每次执行完毕,就会返回到调用位置,这是c++方法栈

然后在C++的代码中构建了一个JVM虚拟机程序,通过这些C++代码,解释执行.class的字节码执行字节码,又会涉及到java的方法调用,通过上面c++代码又构造java栈

同时Java有些时候会调用C++代码,例如Thread.sleep

此外,栈的空间不是特别大一般几mb,可以通过JVM启动参数配置

4、堆(线程共享)

如果t是一个局部变量,t就在栈上,

如果t是一个成员变量,t就在堆上

如果t是一个静态成员变量,t就是在元数据区

元数据和堆整个Java进程公用一个,程序计数器和栈,每个线程有一个

3、JVM类加载

类加载很复杂,从面试角度主要关注两个

1、类加载步骤有哪些

a)加载:找到.class文件,通过累的全限定名 包名+类名 Java.lang.String,打开文件读取内容到内存

b)验证:解析校验.class文件读到的内容是否合法,并把这里内容加载转换成结构化数据

c)准备给类对象申请内存空间,申请的内存空间相当于全0的空间

d)解析针对字符串常量进行初始化~字符串常量本身在.class文件中,通过解析文件的字符串常量放到内存空间里(元数据区,常量池)

e)初始化,针对刚的类对象进行最终的初始化,针对类对象的各种属性进行填充,包括类中的静态成员,如果这个类还有父类,这个环节也会触发加载父类

2、类加载的双亲委派模型是

单亲委派,父亲委派

类加载器,JVM中有专门的模块负责加载类JVM提供了三类加载器

这三个类加载器,首当其冲的就是要进行"找.class文件"环节~com.bit.xxxx.Test给定一个类名,类似于java.lang.String

双亲委派模型的过程:进行类加载,通过全限定类名,找.class的时候就会从ApplicationClassLoader 作为入口开始,然后把加载类这样的任务,委托给父亲来进行,ExtensionClassLoaderExtensionClassLoader 也不会立即进行查找,而是也委托给父亲来进行, BootstrapClassLoaderBootstrapClassLoader 也想委托给父亲,由于没有父亲,只能自己进行类加载.根据类名,找标准库范围,是否存在匹配的.class 文件加载,没找到就抛出异BootstrapClassLoader 没有找到,再把任务还给孩子 ExtensionClassLoader,接下来ExtensionClassLoader 来负责进行.cass 件的过程.找到就加载,没找到,也就把任务还给孩ApplicationClassLoader.接下来ApplicationClassLoader 负责找.class.找到就抛出异常

4、GC垃圾回收

在c语言当中需要手动释放指针,Java里面引入了GC垃圾回收机制

1、找到垃圾(不再使用的对象)

1)引用计数,python php使用,每个对象在new的时候,都搭配一个小的内存空间保存一个整数,每次通过引用计算有多少个引用

缺点1,内存消耗更多吗,如果引用计数4字节,引用本身8字节

2、循环引用问题,如下列代码

2)可达性分析 Java采取这个

1、以代码中的一些特定对象,作为遍历的起点=》GCRoots,

如1栈上的局部变量

2常量池引用指向的对象 程序运行到任何一个时候,JVM都是容易获取到~

3静态成员引用类型

2、尽可能遍历,判断对象能否访问到

3、每一次访问到一个对象,都会把这个对象标记为可达,当完成所有对象遍历之后,未被标记成可达对象就是要回收的垃圾

2、释放垃圾(对于的内存释放)

当知道那些对象是垃圾,如何释放呢

1、标记清理,

把垃圾对象的内存,直接进行释放,但是这样会产生内存碎片问题

虽然空闲空间很多,但是申请一个稍微大一点的内存就会失败,如总内存4g,申请1g可能会失败

2、复制算法

缺点1、内存的空间利用率很低,2一旦垃圾对象不是很多,复制成本很高

3、标记-整理

类似顺序表搬运,但是开销很大

4JVM采用分代回收

某个对象,经历一轮gc可达性分析之后不是垃圾,此时对象年龄+1

如果某个对象已经是一个年龄很大的对象了,此时大概率还会存在很久,如果一个对象是年轻,这个对象可能存在不久,如果是年龄大,可能会一直存在,对于年轻对象可以频繁gc,对于老年对象减少gc次数

新产生的对象放到伊甸区,绝大部分伊甸区对象活不过第一轮gc,通过复制算法将存活对象复制到幸存区,幸存区也会经历gc扫描,释放一大堆对象,剩下的对象再次通过复制算法复制到另一个幸存区,如果这个对象在幸存区经历了多次复制,存活下来,就会放到老年代

相关推荐
mldong27 分钟前
跨语言对齐方法论:参考实现先行 + 契约测试
java·架构
迷枫7121 小时前
SQL性能排查记录
java·数据库·sql
渡我白衣2 小时前
深入理解 Transformer:Transformer 究竟是什么?
java·linux·开发语言·c++·人工智能·深度学习·transformer
Tisfy4 小时前
LeetCode 1927.求和游戏:抵消+看最值
java·leetcode·游戏·题解·博弈论
秋饼11 小时前
JDK 27 企业级 AI 服务落地实战:G1 默认、紧凑对象头、后量子 TLS 与 JFR 脱敏全解析
java·ai·技术分享·后端开发
卓怡学长11 小时前
w176基于SpringBoot的医院管理系统
java·spring boot·spring·maven·intellij-idea
lemon_sjdk11 小时前
ObjectProperty
java·开发语言·算法
hh95011 小时前
Agent Plan x DeepSeek Harness:Agent 供应链安全与第三方插件审计
java·开发语言·安全·agent plan·adg成都社区·adg社区
吴声子夜歌11 小时前
Java面试——HBase原理及应用
java·面试·hbase