真的可惜,四面阿里,结果我被JVM垃圾回收机制与 OOM异常卡住了
前言
为什么需要垃圾回收
- 首先我们来聊聊为什么会需要垃圾回收,假设我们不进行垃圾回收会造成什么后果,我们举一个简单的例子
- 我们住在一个房子里面,我们每天都在里面生活,然后垃圾都丢在房子里面,又不打扫,最后房子都是垃圾 我们是不是就没法住下去了。
- 所以JVM垃圾回收机制也是一样的,当我们创建的对象占据堆空间要满了的的时候我们就对他进行垃圾回收,注意java的垃圾回收是不定时的,c语言的是需要去调用垃圾回收方法
- 刚刚也说到 上面举的例子也说到 假设一个房子都被垃圾堆满了 那么我们没法住人了 那么我们是不是会告诉别人这个房子没法住人了 而java也是如此当我们堆空间满了的时候 此时它就会抛出异常OutOfMemoryError(简称OOM)
什么地方需要进行垃圾回收
刚刚我们说了为什么要回收垃圾,和什么是OOM那么我们下面就给大家介绍,我们JVM中什么地方需要进行垃圾回收。
垃圾回收要考虑的点
1)是否会产生垃圾
2)哪些内存需要回收
3)什么时候回收
4)如何对他进行回收
程序计数器
jvm中唯一 一个不需要垃圾回收的地方。
栈 本地方法栈
这个地方会因为栈帧存满了导致内存溢出,所以需要垃圾回收
方法区(元空间)
这个地方也需要进行垃圾回收
堆
这个地方是我们垃圾回收最频繁的地方,我们几乎我们所有的对象都存储在堆中,也是我们今天要着重讲的地方
堆GC
堆,可能大家都不陌生,可是好像又距离我们很远,今天它来了
从上面的图我们可以看出 ,我们的堆空间被主要被划分为了二块区域 ,新生代 ,老年代 java堆是我们JVM中管理区域最大的一块, java堆是一个线程共享的区域 ,在虚拟机启动时创建 ,几乎所有的对象都在此分配, java虚拟机规范中有过描述,所有的实例对象以及数组都在堆中进行分配内存, 但目前因为JTI编译器的发展,和逃逸分析技术的逐渐完善,在堆中分配对象也不是那么的绝对了。
堆的内存在物理上可以是不连续的,但是在逻辑上是即可。
新生代
- 我们对象的创建到结束,几乎是"朝生夕死"的一个过程差不多90%的对象都在新生代被回收了,所以新生代的gc也是发生最为频繁的一个区域。新生代产生gc我们称为Y-GC
- 每产生一次y-gc我们对象的年龄就加一岁,直到15岁后进入老年代。当然这是正常情况,那么有没有特殊情况勒当然有
空间担保
- 当我们创建的对象大于Eden的时候,此时怎么办,此时他会先产生一次Y-GC如果还是无法存储下新创建的对象,那么我们就会通过空间担保策略进入老年代。
- 还有一种情况,对象创建也会直接进入老年代,当我们的Surivivor区满了的时候,此时它不会主动产生gc只会依赖于Eden,但我们的对象又不能被抛弃,所以它也被分配到了老年代
- 当然我们实际开发工作中需要尽量的去避免这种情况的诞生
动态年龄
- 什么是动态年龄勒,这是堆中的另一个,担保策略了,它会去判断我们Surivivor的区中,相同年龄的对象大于Surivivor区一半的时候,那么他就会判定此时这些对象已经能够很好的存活了,所以他们就集体被丢到老年代了
对象如何分配内存
老年代
- 我们老年代存放的都是一些老对象了,大对象,都是存活时间较长的对象这里一般很少产生FGC这里一旦产生FGC那么所产生GC的耗时将会是YGC的10倍时耗,而我们老年代快要存满时进入了一个对象,这时会产生一次FGC如果GC结束后,还是无法存放对象的话此时就会报OOM异常。
垃圾回收算法
分代算法
分代算法,其实也就是将我们堆空间划分为了一个个不同的区域,新生代,老年代,不让它回收的时候对整个堆进行一个回收。减少GC所停顿的时间,我们称之为STW (Stop The World),假设我们堆整个堆进行垃圾回收,是不是每次都需要去把整个堆的垃圾标记一次,非常的那么用户线程停止的时间就非常长,你想一下,假如你的电脑每使用1个小时就卡10秒,那么你是不是非常操蛋。
标记清除
算法执行过程
堆空间垃圾清理前
垃圾清除后
算法介绍
标记清除是最开始jvm选择的一种垃圾回收算法,这个算法就和他的名字一样,分为标记,和清除二个过程,首先他会标记所有需要回收的对象,标记结束后对标记的对象进行一个垃圾回收。
缺点
这种方式会有什么缺点呢!它会导致内存空间的浪费,产生大佬不连续的内存碎片,当我们需要一个连续的内存空间存放大对象的时候,因为连续的内存空间不够,导致我们不得又产生一次GC,提高了我们GC产生的频率。
标记整理
算法执行过程
算法介绍
标记整理,的执行过程,于标记清除相反,标记清除是标记需要回收的对象,而标记整理却是标记存活的对象,然后把他们全部向一段进行位移,然后清除端边界以外的所有对象。
适用范围
老年代垃圾回收
复制算法
算法执行过程
算法介绍
复制算法也是在标记清除上的一个改进,它弥补了标记清除出现大量不连续内存碎片的缺点。它将一个可用的内存空间划分为大小相等的二块区域,每次只使用其中一块区域,当这块区域用完了就把存活的对象放到,另一块空着的区域区,然后把自己清除干净,变成一块空着的区域。这样就解决了内存碎片的问题
缺点
那么这样的算法是不是太过于苛刻了,每次都需要一块空着的区域用于存放对象,牺牲掉了大量的内存。
适用范围
新生代Surivivor区域
堆中对象内存的分配策略
指针碰撞
这种分配方式其实是复制算法,标记整理中的携带的一种对象分配策略,我们如何区分什么是用过的,什么是没用过的,这时我们通过一个指针,作为一个分界点指示器,那所需要分配的内存,就仅仅是把指示器指针向空闲空间那边挪动一段与对象大小相等的距离,这种分配方式称为"指针碰撞"(Bump the Pointer)。
空闲列表
空闲是标记清除中对对象分配的一个策略,因为标记清除中我们的内存划分的随机的,已使用内存和未使用内存相互交错,那么我们如何把他们关联起来,虚拟机针对这种交错的内存维护了一个列表,记录哪些内存块是可用的,在分配的时候找到一块足够大的空间划分给对象实例,并更新列表上的记录,这种分配方式成为"空闲列表"(Free List)。
OOM异常
其实OOM在上面介绍了堆内存的划分和收集过程中,大家也应该对它有了一定的认识了,OOM异常是发生在老年代Old中的一个异常,当我们老年代中无法在存放对象的时候,就会报OOM内存溢出异常
public class HeapOomError {
public static void main(String[] args) {
List<byte[]> list =new ArrayList<>();
int i=0;
while (true){
try {
Thread.sleep(100);
} catch (InterruptedException e){
e.printStackTrace();
}
list.add(new byte[5 * 1024 * 1024]);
//System.out.println("count is:"+(++i));
}
}
}
设置堆空间的大小

最后我们得到的结果如下

总结
总而言之我们需要的优化的GC的损耗和避免内存溢出的出现,从而提高我用户良好使用体验。
最后
感谢你看到这里,看完有什么的不懂的可以在评论区问我,觉得文章对你有帮助的话记得给我点个赞,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!
真的可惜,四面阿里,结果我被JVM垃圾回收机制与 OOM异常卡住了的更多相关文章
- JVM垃圾回收机制总结:调优方法
转载: JVM垃圾回收机制总结:调优方法 JVM 优化经验总结 JVM 垃圾回收器工作原理及使用实例介绍
- JVM内存管理和JVM垃圾回收机制
JVM内存管理和JVM垃圾回收机制(1) 这里向大家描述一下JVM学习笔记之JVM内存管理和JVM垃圾回收的概念,JVM内存结构由堆.栈.本地方法栈.方法区等部分组成,另外JVM分别对新生代和旧生代采 ...
- JVM垃圾回收机制概述
JVM垃圾回收机制概述 1.定义 是指JVM用于释放那些不再使用的对象所占用的内存. 2.方式 2.1引用计数(早期) 当引用程序创建引用以及引用超出范围时,JVM必须适当增减引用数.当某个对象的引用 ...
- Java虚拟机学习笔记——JVM垃圾回收机制
Java虚拟机学习笔记——JVM垃圾回收机制 Java垃圾回收基于虚拟机的自动内存管理机制,我们不需要为每一个对象进行释放内存,不容易发生内存泄漏和内存溢出问题. 但是自动内存管理机制不是万能药,我们 ...
- JVM基础系列第8讲:JVM 垃圾回收机制
在第 6 讲中我们说到 Java 虚拟机的内存结构,提到了这部分的规范其实是由<Java 虚拟机规范>指定的,每个 Java 虚拟机可能都有不同的实现.其实涉及到 Java 虚拟机的内存, ...
- JVM内存管理、JVM垃圾回收机制、新生代、老年代以及永久代
内存模型 JVM运行时数据区由程序计数器.堆.虚拟机栈.本地方法栈.方法区部分组成,结构图如下所示. JVM内存结构由程序计数器.堆.栈.本地方法栈.方法区等部分组成,结构图如下所示: 1)程序计数器 ...
- JVM 垃圾回收机制和常见算法和 JVM 的内存结构和内存分配(面试题)
一.JVM 垃圾回收机制和常见算法 Sun 公司只定义了垃圾回收机制规则而不局限于其实现算法,因此不同厂商生产的虚拟机采用的算法也不尽相同.GC(Garbage Collector)在回收对象前首先必 ...
- JVM垃圾回收机制和常用算法
由于疫情的原因,所以目前一直在家远程办公,所以很多时间在刷面试题,发现2019大厂的面试虽然种类很多,但是总结了一下发现主要是这几点:算法和数据结构. JVM.集合.多线程.数据库这几点在面试的时候比 ...
- java JVM垃圾回收机制
Java语言出来之前,大家都在拼命的写C或者C++的程序,而此时存在一个很大的矛盾,C++等语言创建对象要不断的去开辟空间,不用的时候有需要不断的去释放控件,既要写构造函数,又要写析构函数,很多时候都 ...
随机推荐
- MVC登录
前言 最近没什么好写的,准备把MVC的登录再写一下,巩固一下 HTML @{ Layout = null; } <!DOCTYPE html> <html> <head& ...
- Vue中键盘事件
Vue中监听 键盘事件及修饰符 键盘事件: keyCode 实际值 48到57 0 - 9 65到90 a - z ( A-Z ) 112到135 F1 - F ...
- 使用Navicat远程连接阿里云ECS服务器上的MySQL数据库
一.必须给服务器的安全组规则设置端口放行规则,在管理控制台中设置: 之后填写配置,授权对象是授权的IP,其中0.0.0.0/0为所有IP授权,之后保存; 二.Navicat使用的配置 在编辑连接处,要 ...
- IntelliJ IDEA 2020.2 x64 激活 2020-09-18亲测有效
idea 激活,查阅许多资源和文章,激活码都失效,无意发现该资源(https://macwk.com/article/jetbrains-crack),亲测有效(2020-09-18),在此记录,以备 ...
- 框架篇:Linux零拷贝机制和FileChannel
前言 大白话解释,零拷贝就是没有把数据从一个存储区域拷贝到另一个存储区域.但是没有数据的复制,怎么可能实现数据的传输呢?其实我们在java NIO.netty.kafka遇到的零拷贝,并不是不复制数据 ...
- B. Nauuo and Circle 解析(思維、DP)
Codeforce 1172 B. Nauuo and Circle 解析(思維.DP) 今天我們來看看CF1172B 題目連結 題目 略,請直接看原題 前言 第一個該觀察的事情一直想不到,看了解答也 ...
- SpringBoot连接多数据源(HBASE,KUDU,ORACLE集成和开发库)
前提:1.连接hadoop需要本地安装 winutils.exe 并在程序指定,不然程序会报错 IOException: HADOOP_HOME or hadoop.home.dir are not ...
- 云计算之路-出海记:蹭一张 aws 船票
出海记开篇之后,在 aws 上搭建博客园海外站的出海计划今天开始迈出第一步 -- 注册一个 aws 海外区域账号. aws 现在针对新注册用户提供12个月免费套餐(正在园子里推广并提供了专属注册通道) ...
- 面试小问题——Object中有哪些常用方法?
一.equals方法 Object类中的equals方法用于检测一个对象是否等于另外一个对象.Java语言规范要求equals方法具有下面的特性: (1)自反性:对于任何非空引用x,x.equals( ...
- Jmeter——ForEach Controller&Loop Controller
今天来分享下Jmeter中的2款循环控制器,ForEach Controller和Loop Controller,在使用上还是有所区别. ForEach Controller ForEach Cont ...