JVM(2)

学习日记-JVM(2)

  • 主管程序的运行,生命周期和线程同步
  • 对于栈来说,不存在垃圾回收
  • 8大基本类型+对象引用+实例的方法

堆(Heap)

  • 一个jvm只有一个堆内存,堆内存大小是可以调节的
  • 堆内存分为三个区域:新生区(伊甸园区,幸存区0区,幸村区1区),养老区(老年代),永久区(jdk1.8后改为元空间)
  • 堆内存满了,会产生OOM错误

新生区

  • 类诞生和成长的地方,甚至死亡
  • 伊甸园,所有的对象都是在伊甸园区new出来的,满了出现一次轻量级垃圾回收

永久区

  • 常驻内存,用来存放jdk自身携带的class对象,interface元数据,存储一些java运行时环境和类信息,这个区域不存在垃圾回收
  • jdk1.6之前:永久代,常量池在方法区
  • jdk1.7:永久代,慢慢退化,出现去永久代,常量池在堆中
  • jdk1.8:无永久代,常量池在堆中

Jprofiler

  • 分析dump文件,快速定位内存泄漏
  • 获取堆中的数据,获得大的对象等
    jvm2

垃圾回收(GC)

  • JVM GC只回收堆区和方法区内的基本类型数据和对象。
  • 回收:对象没有引用了或者对象不可达
  • 怎么判断对象是否存活?常见的有两种算法,分别是 引用计数法 和 可达性分析法

引用计数法

  • 在对象里添加一个被引用的计数器,每当有地方引用了它,计数器就加1,引用失效时,计数器就减1。
  • 在触发回收内存的时候,遍历所有对象,把计数器值等于0的找出来,释放掉即可。无法回收互相引用的对象

标记 - 清除算法

  • 首先标记出所有存活的对象,再扫描整个空间中未被标记的对象直接回收。
  • 标记的是“存活”的对象,再进行清除,只需要两个步骤即可:
    • 先通过可达性分析法,通过根对象(GC Roots)顺着引用链先把这些存活对象都标出来
    • 遍历这个区域所有对象,把没标记存活的对象,直接清理掉即可。
  • 缺点:由于回收后没有进行整理的操作,所以会存在内存空间碎片化的问题

标记 - 复制算法(新生区)

  • 常规的复制算法,是把内存分成两块大小相同的空间(1 : 1),每次只使用其中一块,当使用中的这块内存用完了,就把存活的对象移动到另一块内存中,再把使用过的这块内存空间一次性清理掉
  • 标记-复制算法,在这个基础之上对其进行了优化,IBM曾有过一项针对新生代的研究,结论是绝大多数情况下,新生代区域里的对象有98%都熬不过第一次回收。所以不需要按照 1 : 1 的比例来实现复制算法,而是可以按照 8 : 1 : 1 的比例来分配内存空间,也就是一个80%的Eden空间和两个10%的Survivor空间。
  • 每次分配内存,只使用Eden和其中一块Survivor空间,发生GC回收时,把Eden和其中一块Survivor空间中存活的对象,复制到另一块空闲的Survivor空间,然后直接把Eden和使用过的那块Survivor空间清理掉。

标记 - 整理算法(老年区)

  • 标记-清除算法会产生内存碎片,不适合哪些需要大量连续内存空间的场景,而标记-整理算法,就是在其基础之上,增加了整理这个操作,去解决这些内存空间碎片化的问题
  • 和标记-清除算法一样,先标记,但清除之前,会先进行整理,把所有存活的对象往内存空间的左边移动,然后清理掉存活对象边界以外的内存,即完成了清除的操作。标记-整理 算法是在 标记-清除 算法之上,又进行了对象的移动排序整理,因此成本更高,但却解决了内存碎片的问题。
  • 老年代里的对象存活率很高,不适合使用标记-复制的算法。而且老年代存储大对象的概率要比新生代大很多,这些大对象需要连续的内存空间来存储,标记-清除这个算法也不适合。所以大多数的老年代都采用标记-整理来作为这个区域的回收算法。
  • 40
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值