jvm:内加载+垃圾回收

文章目录

本文主要是讲解我对JVM的类加载、垃圾回收这两方面的理解

类加载

我们都知道咱们编写一个java类后经过编译会生成一个class文件,然后再由JVM来执行,那么JVM是怎么加载这个class文件的嘞?
其实这都是由ClassLoader 和它的子类来完成的,它其实就是一个类,它是java运行时的一个组件,它就是负责在运行时查找和装载class文件。
然而类加载还分为隐式加载和显式加载。隐式加载就是我们平时使用new创建对象,而显式加载就是使用反射Class.forname()等方式。
当一个类加载器收到了类加载的请求后并不会立刻执行加载的请求,而是让父类去加载,以此往复,当父类不能加载时才会当前类加载。
一个类的加载总共分为五个阶段:

  1. 加载。简而言之就是在内存中创建一个暂时可以代表整个类的java.lang.Class对象;
  2. 验证。其实就是验证class文件是否安全,是否满足JVM的要求,是否会对JVM产生危害;
  3. 准备。为类中的变量分配内存空间以及赋初始值;
  4. 解析。将常量池中符号引用替换为直接引用;
  5. 初始化。其实就是执行构造函数的过程。

垃圾回收

JVM将堆分为了两个部分,一个的新生代,另一个的老年代。新生代占1/4的内存空间,老年代占3/4的空间。新生代又将内存按照8:1:1的比例分为了Eden空间、From Survivor和To Survivor 。
新创建的对象总是在Eden区中,From survivor区中存放还存活的对象,To survivor为空。当Eden中存放的对象块满了的时候就会进行一个gc ,将Eden 和From survivor区中的对象转移到To survivor中 。并清空Eden 和 From survivor区。然后让From survivor 和 To survivor颠倒,From survivor 变为 To survivor,To survivor变为 From survivor。重复进行了多次后,将存活的对象转入老年代。

接下来再谈谈gc的几种算法。

  • 引用计数法。这其实就是当创建一个对象A 被对象B引用。引用计数器为1,每多一个引用 计数器就自增1。当一次引用失效后计数器自减。当计数器为0时就可以被垃圾回收了;
  • 标记清除算法。首先从根节点开始,标记所有根节点的可达对象。当标记完成后,没有标记的对象就是不可达的垃圾对象。使用标记清除算法会产生大量的空间碎片化,因为回收的空间不是连续的。
  • 复制算法。它比较快速但是不适合于存活对象很多的场合,它将老年代分为了两块,每次使用其中的一块,在垃圾回收时,将存活的对象复制至另一块,然后清空之前的那一块内存。以此往复。
  • 标记整理算法,也叫标记压缩算法。复制算法是在垃圾对象多,存活对象少的前提下速度才快,但是如果存活对象很多的情况下复制算法的成本也很高。而标记整理算法在标记清理算法上做了一些优化。也是现从根节点出发,标记所有可达对象。然后将可达对象压缩到内存的一端,然后清除边界外的所有空间,这样既可以避免空间碎片化,并不像复制算法那样需要两块内存空间。

最后再谈谈java中的内存泄漏的问题吧。内存泄漏其实就是不会再被使用的垃圾对象不能被回收,那么什么情况下会产生内存泄漏的问题嘞? 其实就是一个生命周期很长的对象引用了一个生命周期很短的对象。还有就是一个资源对象没有被释放的情况下也会产生内存泄漏。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值