滴滴滴滴滴

1jvm

方法区,堆

程序计数器,本地方法栈,虚拟机栈

常量,静态变量,对象,字节码指令地址(jvm翻译的就是.class文件),c和c++。

方法区:常量,静态变量

堆:对象,成员变量。

程序计数器:字节码指令地址

本地方法栈:c和c++

虚拟机栈:局部变量

堆、方法区(永久代 / 元空间)、虚拟机栈 / 本地方法栈、直接内存,均可能抛出 OutOfMemoryError

程序计数器内存区域是虚拟机中唯一没有规定OutOfMemoryError情况的区域。

直接内存与堆内存的区别:

直接内存申请空间耗费很高的性能,堆内存申请空间耗费比较低

直接内存的IO读写的性能要优于堆内存,在多次读写操作的情况相差非常明显

虚拟机核心的组件就是执行引擎,它负责执行虚拟机的字节码,JVM字节码被执行引擎编译成机器码后才可在物理机上执行。

一些没有引用指向的内存对象都属于内存垃圾。

垃圾回收机制简称GC。GC主要用于Java堆的管理。

finalize()方法是在每次执行GC操作之前时会调用的方法,它是在Object类中定义的,因此所有的类都继承了它。

新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 --XX:NewRatio 来指定 ),即:新生代 ( Young ) = 1/3 的堆空间大小。老年代 ( Old ) = 2/3 的堆空间大小。

  1. 在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old ),

  2. 老年代就一个区域。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。

默认的,Edem : From Survivor : To Survivor = 8 : 1 : 1 ( 可以通过参数 --XX:SurvivorRatio 来设定 ),即: Eden = 8/10 的新生代空间大小,From Survivor = To Survivor = 1/10 的新生代空间大小。

永久代就是JVM的方法区。

  1. 新生代中,每次垃圾收集时都发现大批对象死去,只有少量对象存活,便采用了复制算法,只需要付出少量存活对象的复制成本就可以完成收集。

  2. 而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须采用"标记-清理"或者"标记-整理"算法。

大概流程:

新生代又分为Eden和Survivor (From与To,这里简称一个区)两个区。加上老年代就这三个区。数据会首先分配到Eden区当中(当然也有特殊情况,如果是大对象那么会直接放入到老年代(大对象是指需要大量连续内存空间的java对象)。当Eden没有足够空间的时候就会触发jvm发起一次Minor GC,。如果对象经过一次Minor-GC还存活,并且又能被Survivor空间接受,那么将被移动到Survivor空间当中。并将其年龄设为1,对象在Survivor每熬过一次Minor GC,年龄就加1,当年龄达到一定的程度(默认为15)时,就会被晋升到老年代中了,当然晋升老年代的年龄是可以设置的。

Minor GC:新生代GC

Major GC:老年代GC,通常执行Major GC会连着Minor GC一起执行。

Full GC:清理整个堆空间,包括年轻代和老年代

Minor GC 触发条件一般为:

1.eden区满时,触发MinorGC。即申请一个对象时,发现eden区不够用,则触发一次MinorGC。

2.​ 新创建的对象大小 > Eden所剩空间
Major GC和Full GC 触发条件一般为:

Major GC通常是跟full GC是等价的

1每次晋升到老年代的对象平均大小>老年代剩余空间

2MinorGC后存活的对象超过了老年代剩余空间

3永久代空间不足

4执行System.gc()

5CMS GC异常

6堆内存分配很大的对象

如何判断对象是否存活

1。引用计数法:每个对象在创建的时候,就给这个对象绑定一个计数器。每当有一个引用指向该对象时,计数器加一;每当有一个指向它的引用被删除时,计数器减一。这样,当没有引用指向该对象时,计数器为0就代表该对象死亡。建议不要用

  1. 可达性分析法:该种方法是从GC Roots开始向下搜索,搜索所走过的路径为引用链。当一个对象到GC Roots没用任何引用链时,则证明此对象是不可用的,表示可以回收。这是目前主流的虚拟机都是采用的算法
垃圾回收机制策略(也称为GC的算法)

1.引用计数算法:

每个对象在创建的时候,就给这个对象绑定一个计数器。每当有一个引用指向该对象时,计数器加一;每当有一个指向它的引用被删除时,计数器减一。这样,当没有引用指向该对象时,计数器为0就代表该对象死亡,这时就应该对这个对象进行垃圾回收操作。建议不要用

2.标记--清除算法(Mark-Sweep):

为每个对象存储一个标记位,记录对象的状态(活着或是死亡)。

分为两个阶段,一个是标记阶段,这个阶段内,为每个对象更新标记位,检查对象是否死亡;第二个阶段是清除阶段,该阶段对死亡的对象进行清除,执行 GC 操作。该算法一般应用于老年代,因为老年代的对象生命周期比较长。

3.标记--整理算法

标记-整理法是标记-清除法的一个改进版。同样,在标记阶段,该算法也将所有对象标记为存活和死亡两种状态;不同的是,在第二个阶段,该算法并没有直接对死亡的对象进行清理,而是将所有存活的对象整理一下,放到另一处空间,然后把剩下的所有对象全部清除。这样就达到了标记-整理的目的。该算法一般应用于老年代,因为老年代的对象生命周期比较长。

4.复制算法

该算法将内存平均分成两部分,然后每次只使用其中的一部分,当这部分内存满的时候,将内存中所有存活的对象复制到另一个内存中,然后将之前的内存清空,只使用这部分内存,循环下去。

  • 复制算法一般是使用在新生代中,因为新生代中的对象一般都是朝生夕死的,存活对象的数量并不多,这样使用复制算法进行拷贝时效率比较高。
  • jvm将Heap(堆)内存划分为新生代与老年代。又将新生代划分为Eden与2块Survivor Space(幸存者区) ,然后在Eden -->Survivor Space 与To Survivor之间实行复制算法。

5.分代算法(主要的算法就是上面四种,这个是附加的)

垃圾收集器
  • 新生代收集器:Serial、ParNew、Parallel Scavenge

  • 老年代收集器:CMS、Serial Old、Parallel Old

  • 整堆收集器:G1

搭配使用:

Serial / Serial Old

Serial / CMS

ParNew / Serial Old

ParNew / CMS

Parallel Scavenge / Serial Old

Parallel Scavenge / Parallel Old

G1

cms:以获取最短回收停顿时间为目标。CMS收集器有3个明显的缺点:1.对CPU资源非常敏感、2.无法处理浮动垃圾,可能出现"Concurrent Mode Failure"失败、3.产生大量内存碎片

g1:采用标记-整理 + 复制算法来回收垃圾

相关推荐
LiRuiJie2 小时前
从OS层面深入剖析JVM如何实现多线程与同步互斥
java·jvm·os·底层
董世昌412 小时前
深度解析var、let、const的区别与最佳使用场景
开发语言·前端·javascript
FJW0208142 小时前
Python中的闭包
开发语言·python
C_心欲无痕2 小时前
Next.js 平行路由:构建模块化动态布局
开发语言·前端·javascript
张乔242 小时前
spring boot项目中设置默认的方法实现
java·数据库·spring boot
100编程朱老师2 小时前
fping命令详解
开发语言·php
heartbeat..2 小时前
数据库性能优化:SQL 语句的优化(原理+解析+面试)
java·数据库·sql·性能优化
matlabgoodboy2 小时前
生信分析服务医学统计数据分子对接网络药理学单细胞测序r语言geo
开发语言·r语言
Qhumaing2 小时前
Java学习——第五章 异常处理与输入输出流笔记
java·笔记·学习