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扫描,释放一大堆对象,剩下的对象再次通过复制算法复制到另一个幸存区,如果这个对象在幸存区经历了多次复制,存活下来,就会放到老年代

相关推荐
盖伦发发6 小时前
Redis 核心教学: 数据结构, 缓存设计, 分布式锁
java·redis·后端·软件工程
卷毛的技术笔记6 小时前
RocketMQ事务消息:我把分布式事务这层窗户纸捅破了
java·分布式·后端·java-rocketmq
yxlalm6 小时前
零基础快速上手Trae创建Java项目
java·人工智能
ly76896 小时前
磁盘 I/O 延迟突增:用 iostat、blktrace 与火焰图定位到具体调用栈
java·linux·前端·数据库·iostat·磁盘 i/o·blktrace
泡海椒6 小时前
jquick-pdf 核心原理解析:基于 HTML 模板动态渲染 PDF 的实现逻辑
java·开发语言·pdf
Bs_MoneyMagnet6 小时前
基于springboot+vue的图书馆预约系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·毕业设计·图书管理系统·计算机毕业设计
小蒜学长7 小时前
基于小程序的绘画作品创作与分享社区系统的设计与实现(代码+数据库+LW)
java·spring boot·后端·绘画作品·创作分享社区
金玉满堂@bj7 小时前
# Java文件打包成可执行JAR包(两种方式:原生javac\+jar命令 / Maven)
java
事圆则缓7 小时前
Java 异常、日志与 Android 崩溃定位
java
砍材农夫8 小时前
spring|spring web|拦截器、过滤器、aop
java·spring boot·spring·spring cloud