虚拟机垃圾收集机制探寻与代码优化

1.JVM内存模型中几个重要区域的作用?
1.1 方法区:主要存储了类class的信息、静态属性、常量等
1.2 堆:主要存储的是对象、数组
1.3 栈:主要是线程执行方法的地方,每个方法调用一个栈帧
2.GC怎么发现垃圾?
2.1 引用计数法:原理是如果某个对象有一个引用,则+1;删除一个引用,则-1。GC只用收集计数为0的对象。**它的优点是:**效率比较高。缺点是:(1)无法处理循环引用的问题。如:对象A和B分别有字段b、a,令A.b=B和B.a=A,除此之外这2个对象再无任何引用,那实际上这2个对象已经不可能再被访问,但是引用计数算法却无法回收他们。2)引用计数的方法需要编译器的配合,编译器需要为此对象生成额外的代码。如赋值函数将此对象赋值给一个引用时,需要增加此对象的引用计数。还有就是,当一个引用变量的生命周期结束时,需要更新此对象的引用计数器。
2.2 根搜索法:它的处理方式就是,设立若干种根对象,当任何一个根对象到某一个对象均不可达时,则认为这个对象是可以被回收的。
在这里插入图片描述
如上图:对象1的根是reference1,对象2的根是reference2,对象4的根是reference3,对于对象6来说它的根是对象4,而对象4是有根的,所以对象6不是垃圾。对象三的根是对象5,但是对象5并没有根,所以根据根搜索法对象3和对象5是会被GC当成垃圾回收。如果用引用计数法的话对象3和对象5都不能被当做垃圾回收。所以目前JVM都是采用根搜索法来收集垃圾的。
3.GC怎么回收垃圾?
3.1 标记清除法:它的做法是当堆中的有效内存空间被耗尽的时候,就会停止整个程序,然后进行两项工作,第一项则是标记,第二项则是清除。(1)标记:标记的过程其实就是,遍历所有的GC Roots,然后将所有GC Roots可达的对象标记为存活的对象。(2)清除:清除的过程将遍历堆中所有的对象,将没有标记的对象全部清除掉。缺点:(1)相对于递归与全堆对象遍历效率比较低。(2)这种方式清理出来的空闲内存是不连续的。在分配数组对象的时候,寻找连续的内存空间会不太好找。
3.2 分段复制法:复制算法将内存划分为两个区间,在任意时间点,所有动态分配的对象都只能分配在其中一个区间(称为活动区间),而另外一个区间(称为空闲区间)则是空闲的,当有效内存空间耗尽时,JVM将暂停程序运行,开启复制算法GC线程。接下来GC线程会将活动区间内的存活对象,全部复制到空闲区间,且严格按照内存地址依次排列,与此同时,GC线程将更新存活对象的内存引用地址指向新的内存地址。此时,空闲区间已经与活动区间交换,而垃圾对象现在已经全部留在了原来的活动区间,也就是现在的空闲区间。**缺点:**效率比较低,会有一定的空间浪费。
3.3 标记/整理算法:标记/整理算法与标记/清除算法非常相似,它也是分为两个阶段:标记和整理。(1)标记:它的第一个阶段与标记/清除算法是一模一样的,均是遍历GC Roots,然后将存活的对象标记。(2)整理:移动所有存活的对象,且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收。因此,第二阶段才称为整理阶段。**优点:**标记/整理算法不仅可以弥补标记/清除算法当中,内存区域分散的缺点,也消除了复制算法当中,内存减半的高额代价。**缺点:**标记/整理算法唯一的缺点就是效率也不高,不仅要标记所有存活对象,还要整理所有存活对象的引用地址。从效率上来说,标记/整理算法要低于复制算法。
3.4 分代收集法:分代收集发包括伊甸园、生存区、老年代、永久代(方法区)。伊甸园里面包含了最新的对象,所以GC在伊甸园活动的概率会比较高。而通过了伊甸园还没被回收的对象则会到达生存区,生存区里面包含了From、To区,这两个区里面使用了分段复制发来清除垃圾。当通过了生存区没有被回收的对象会到达老年代,在老年代GC活动的概率比较低,而在老年代会使用标记整理法来回收垃圾,没有被回收的对象则会到达永久代也就是方法区,在永久代一般GC活动的概率很低,而在永久代的对象一般也会永久存活。目前垃圾回收用的方法也是此方法。
4.高效代码的技巧?
4.1 尽量不要在循环中使用try-catch、new对象
4.2 把频繁使用的短命对象缓存起来
4.3 尽可能使用栈内变量(方法内局部变量)
4.4 用线程池、连接池,不要自己创建
5.内存泄漏和内存溢出?
5.1 内存泄漏:该回收的内存、对象,无法回收导致内存一直被占用,这就导致了内存泄露。
5.2 内存溢出:内存不够了,导致程序崩溃,所以导致了内存溢出。内存泄露也会导致内存溢出。(1)堆内存溢出:使用-Xms -Xmx调整堆内存大小。OutOfMemoryError:Heap sapce堆内存溢出错误。(2)方法区溢出:使用 - XX:MetaspaceSize= -XX:MaxMetaspaceSize= 调整方法区的内存大小。OutOfMemoryError:Metaspace方法区内存溢出。(3)栈内存溢出:使用 -Xss 调整栈内存的大小。**StackOverflowError:**栈内存溢出错误。
6.JVM内存参数?
6.1 调整堆内存大小:-Xms20M -Xmx50M
6.2 调整栈内存大小:-Xss66M
6.3 调整方法区内存大小: - XX:MetaspaceSize=30M -XX:MaxMetaspaceSize= 60M(- XX:PermSize=30M -XX:MaxPermSize= 60M jdk 1.7之前版本适用)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值