JAVA的内存回收机制(快速入门版)

java内存回收机制

内存回收,是JVM中垃圾回收器提供的一种用于在空闲时间不定时回收无任何对象引用的对象占据的内存空间的一种机制

引用 :

java中什么是引用?

Person xiaoi =new Person();

new person()以person类为模板,创建一个person类的对象,括号代表对象创建后,立刻调用person类的构造函数,并对该对象进行初始化。左边的person xiaoi就是创建了一个peeson类的引用变****量,用来指向person对象的对象引用

​ 如果reference类型的数据存储的数值代表的是另一块内存的地址,就称这块内存代表着一个引用

强引用

​ 就像Object object =new Object() 这类引用是Java程序中最普遍的,只要强引用还在 垃圾回收器就永远不会回收掉被 引用的对象

软引用

soft reference 描述一些可能还有用,非必须的对象。 系统内存不够的时候,这类引用关联的对象将被垃圾收集器回收 jdk1.2之后提供了soft reference类来实现软引用

弱引用

weak reference 用来描述比软引用更弱,只能活到垃圾回收器到来之前,jdk1.2之后提供了weak reference类实现弱引用

虚引用

最弱,为一个对象设置虚引用是为了在被垃圾收集器回收的时候收到一个通知

怎么判断垃圾

1 引用计数算法

每个对象都有一个引用计数器,当对象被创建并赋初始值之后,变量计数为1,每当一个地方引用他就+1 引用失效就-1,等于0就会被垃圾收集

​ 优点:简单,执行率高

​ 缺点: 没办法检测出对象中的循环引用,同时计数器增加程序开销

2根搜索算法

根集就是正在执行的java程序可以访问的引用变量的集合(包括局部变量,参数,类变量

程序可以使用引用变量访问对象的属性和调用对象的方法

基本思路是

1 通过一系列名为gc roots的对象作为起始点,寻找对应的引用节点

找到这些引用节点后 从这些节点向下开始寻找他们的引用节点

​ 重复上一步

​ 搜索走过的路径称之为引用链,当一个对象到gc roots没有任何引用链链相连时候,就说明这个对象是不可用的

gcroot

​ 包括虚拟机栈中引用的对象 方法区中常量引用的对象 方法区中的类静态属性引用的对象 本地方法中jni的引用对象 活跃的线程

标记注意点

标记前要暂停应用线程 这种暂停线程的做法叫安全点safe point 常见出现安全点的原因就是垃圾回收

暂停时间的长短取决于存活对象的多少

根搜索算法中 要经历两次标记过程才会宣告一个对象的死亡

​ 第一次标记----进行一次筛选(筛选条件:是否有必要执行finalize方法)

​ 有必要执行的–进入队列—进行第二次筛选(筛选条件:是否通过finalize方法中重新进入引用链)

finalize方法

​ 目的是在对象不在被需要 将被丢弃之前执行清除操作(例如输入输出连接的对象可能会在丢弃之前断开连接操作)

回收垃圾的算法

1 标记-清除算法

使用根集的概念,标记出所有回收的对象 标记完成后统一回收

优点:

不需要对象移动,存活对象多的时候极为高效

缺点

效率不高

会产生大量不连续的内存碎片,引发第二次垃圾回收

2标记-整理

标记后将所有对象向一边移动,然后清理掉边界之外的内存

优点

新对象的分配只要通过指针碰撞就能完成(指针碰撞,有个指针作为空闲与否的分界线,那么为新对象分配内存空间只需要指针往后加需要的大小就可以)

缺点

gc暂停时间延长(要把所有的对象拷贝到新的地方)

3copying算法

将内存分为两半,一块用完了,就将还存活着对象复制到另外一块内存上,直接清理掉另一块内存

优点

标记和复制阶段同时进行

每次只要回收一半(一块的内存) 效率高

分配内存方便,移动栈顶指针即可

内存回收不需要考虑内存碎片的出现

缺点

一次性可以分配的最大内存缩小了一半

如果活着的对象很多,复制就会很费性能(比如在老年代中的对象,生存期很长) 比较适合活着的对象很短的新生代

adaptive算法

根据堆的使用情况来选择合适的算法

java堆内存分配区域

年轻代

新生成对象存放处, 分成 eden servicor1 和servivor0区 分配比例8.1.1

当eden满,触发一次gc,将eden区存活的对象放到ser0,清空eden

如果ser0满就存到1,然后清空eden和ser0

如果1也满了,存活的对象会直接进入老年代

如果一个对象躲过1次gc 年龄gc 如果大于设置好的年龄(默认15) 就会进入老年代

如果老年代也满了会触发一次全gc 这样会让老年代新生代都进行回收

年轻代大部分的对象都会很快死去,因此minor gc很频繁,可以用复制算法

老年代

存放的都会生命周期较长的对象 内存比例也会高很多,同时一些大对象会直接分配到老年代

由于都是生命周期长 对象 用复制算法会浪费时间,因此使用标记清除算法会好很多

持久代

存放静态文件 在javase8后变了元空间

垃圾回收器的类型

串行垃圾回收器

单线程回收,冻结所有应用程序,不适合服务器环境

并行垃圾回收器

多线程回收,一样会冻结所有应用程序,适合多cpu 对暂停时间要求较短的

并发标记扫描垃圾回收器

多线程扫描堆内存,使用更多的cpu进行,只有一些特殊情况才会冻结所有应用程序

G1垃圾回收器

最先进的收集器,面向服务端,充分利用多cpu多核环境 可以并行并发收集 适合于很大堆内存的情况

垃圾回收的执行时间

GC分为Scavenge GC和Full GC。

Scavenge GC :发生在Eden区的垃圾回收。

Full GC :对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个堆进行回收,所以比Scavenge GC要慢,因此应该尽可能减少Full GC的次数。在对JVM调优的过程中,很大一部分工作就是对于FullGC的调节。

1.年老代(Tenured)被写满;

2.持久代(Perm)被写满;

3.System.gc()被显示调用;

4.上一次GC之后Heap的各域分配策略动态变化.

。触发主gc的条件

1程序空闲(线程优先级最低,忙的时候不出现

2堆内存满了 (一次gc不行就两次gc 两次不行报oom)

减少gc开销的措施

1 不要显式调用system.gc();

2 减少临时对象的使用

3 不用的对象最好显式置为null

4 尽量使用stringbuffer而不是string进行字符拼接 (string累加会生成很多垃圾对象)

5尽量使用基本类型(包装类型占用资源)

6 少使用静态变量

7 分散对象创建或者删除的时间

GC性能调优

下次再讲

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值