大岭山镇网站建设,网站建设打造营销型网站,wordpress支付后可见,关键词排名seo优化JVM垃圾回收
1 简单说下Java垃圾回收机制#xff1f;
首先在java运行过程中#xff0c;其实程序员并不需要去显示的调用程序来释放对象的内存#xff0c;而是由虚拟机来完成的#xff0c;具体来看是在jvm中有个垃圾回收线程#xff0c;这个线程是个守护线程#xff0c;…JVM垃圾回收
1 简单说下Java垃圾回收机制
首先在java运行过程中其实程序员并不需要去显示的调用程序来释放对象的内存而是由虚拟机来完成的具体来看是在jvm中有个垃圾回收线程这个线程是个守护线程这个线程会在虚拟机空闲或者在当前堆内存不足时才会触发执行扫面那些没有被任何引用的对象并将它们添加到要回收的集合中进行回收。
2 垃圾回收器的基本原理是什么优点有哪些垃圾回收器可以马上回收内存吗
其实jvm的垃圾回收在我们一开始创建对象的时候GC就会去监控这个对象的地址大小和使用情况而jvm在进行回收的时候主要是采用了可达性分析算法通过这种方式确定哪些对象是可达 的哪些对象是不可达的。当GC确定一些对象为不可达时GC就有责任回收这些内存空间。 其实垃圾回收的优点也很明显首先就是不用像其他语言一样需要程序员手动的去释放内存其次垃圾回收机制可以有效的防止内存泄露并且可以做到对内存进行更有效的利用。 对于垃圾回收的时机虽然程序员可以通过执行System.gc()通知GC运行但是Java语言规范并不保证GC一定会执行。
3 怎么判断对象是否可以被回收
我们刚才说到jvm会自动的对内存进行回收因此它在回收的时候就需要知道 哪些对象是存活的不需要被回收而哪些对象又是垃圾对象可以被回收那么它具体是怎么判断的呢 其实有两种判断方式 1 引用计数法说白了也就是会为每一个对象创建一个引用计数有对象引用时计数器会加1而引用释放时计数器会减1而当计数器为0时也就表示对象可以被回收它有一个缺点就是不能解决循环引用的问题 2 可达性分析算法也就是会从GC root开始向下搜索搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时则证明此对象是可以被回收的。
4 JVM 运行时 堆内存如何分代?
Java 堆从 GC 的角度还可以细分为: 新生代和老年代。 而新生代 又可以分为 (Eden 区、 From Survivor 区和 To Survivor 区) 一般新生代和老年代的比例约为 1:2 同时 eden区s1区s2区约为 8:1:1 同时对于新生代来说 JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务所以无论什么时候总是有一块 Survivor区域是空闲着的。 整体的流程就是 新建的对象会首先分配在Eden区中经历一次Minor GCEden中的存活对象就会被移动到第一块survivor S0区Eden被清空等Eden区再满了就再触发一次Minor GCEden和S0中的存活对象又会被复制送入第二块survivor S1 区就是通过这样不断地复制–清空—互换来实现年轻代的垃圾回收即minor gc 同时年轻代采用复制算法也解决了内存碎片化的问题
我们接着再看老年代 老年代的对象特点 一般都是长生命周期的对象也就是比较稳定因此 MajorGC 常常称之为 FULL GC不会频繁执行。 同时注意在进行 FULL GC前一般都先进行了一次 MinorGC使得有新生代的对象晋身入老年代导致空间不够用时才触发。当无法 找到足够大的连续空间分配给新创建的较大对象时也会提前触发一次 MajorGC 进行垃圾回收腾出空间。 FULL GC 采用标记清除算法同时会产生内存碎片
永久代 或者 jdk1.8元空间 指内存的永久保存区域主要存放 Class 和 Meta元数据的信息,Class 在被加载的时候被放入永久区域 它和和存放实例的区域不同,GC 不会在主程序运行期对永久区域进行清理。所以这也导致了永久 代的区域会随着加载的 Class 的增多而胀满最终抛出 OOM 异常。
5 JVM内存为什么要分成新生代老年代永久代即为什么要分代新生代中为什么要分为Eden和Survivor
这个问题 其实想一下就能理解 分代主要还是 为了提高对象内存分配和垃圾回收的效率。 试想一下如果堆内存没有区域划分所有的新创建的对象和生命周期很长的对象放在一起随着程序的执行堆内存需要频繁进行垃圾收集而每次回收都要遍历所有的对象遍历这些对象所花费的时间代价是巨大的会严重影响我们的 GC 效率。
而有了内存分代情况就不同了新创建的对象会在新生代中分配内存经过多次回收仍然存活下来的对象存放在老年代中 静态属性、类信息等存放在永久代或者元空间中 新生代中的对象存活时间短只需要在新生代区域中频繁进行 GC老年代中对象生命周期长内存回收的频率相对较低不需要频繁进行回收。
而新生代为什么要分为eden区和survivor区
我们试想下 如果没有SurvivorEden区每进行一次Minor GC存活的对象就会被送到老年代。这样一来老年代很快被填满触发Major GC. 又因为老年代的内存空间远大于新生代进行一次Full GC消耗的时间比Minor GC长得多, 所以总结来看 分为eden区 和s区可以减少对象频繁地被输送到老年代进而减少了full gc的发生。同时分为两个eden区利用这种复制算法也避免了内存的碎片化。
6 JVM中一次完整的GC流程是怎样的对象如何晋升到老年代?
针对这个问题思路就是可以先描述下java堆内存的划分以及minor gcmajor gcfull gc 以及他们之间的转换过程。 首先我们知道java堆可以分为 老年代 新生代同时 新生代 Eden S0 S1 整体的过程就是
当 Eden 区的空间满了 Java虚拟机会触发一次 Minor GC以收集新生代的垃圾存活下来的对象则会转移到 Survivor区。而 如果对象在Eden出生并经过第一次Minor GC后仍然存活并且被Survivor容纳的话年龄设为1每熬过一次Minor GC年龄1若年龄超过一定限制15----即经过静态年龄判断规则后则被晋升到老年态。即长期存活的对象进入老年态。 当然对于大对象 比如那种连续内存空间的java对象比如那种很长的字符串也会直接进入老年代当老年代满了无法容纳更多的对象就会发生major gc清理掉老年代同时major gc会伴随着至少一次minor gc。而Full GC 会清理整个内存堆 – 包括年轻代和年老代。
那么Minor GC与Full GC分别在什么时候发生 新生代内存不够用时候发生minor gc也叫YGCJVM内存不够的时候发生FGC
7 JVM 有哪些垃圾回收算法
可以分为 四种即标记-清除算法复制算法标记整理算法 分代收集算法 我们首先看标记清除算法 该算法分为“标记”和“清除”阶段首先标记出所有不需要回收的对象在标记完成后统一回收掉所有没有被标记的对象。 适用场合存活对象较多的情况、适用于年老代。 优点比较简单不需要对象的移动 缺点会产生大量的内存碎片效率也比较低
复制算法 因为标记清除算法会产生内存碎片 因此在他的基础之上引入复制算法 说白了复制算法 就是 把内存空间划为两个相等的区域每次只使用其中一个区域。 垃圾收集时遍历当前使用的区域把存活对象复制到另外一个区域中最后将当前使用的区域的可回收的对象进行回收。 优点按顺序分配内存即可实现简单、运行高效不用考虑内存碎片。 缺点可用的内存大小缩小为原来的一半对象存活率高时会频繁进行复制。
标记整理算法 刚才说了复制算法 解决了内存碎片化的问题但是它也有一个问题就是内存的使用率并不高需要频繁地进行来回复制 因此又引入了标记整理算法说白了 就是在标记可回收的对象后将所有存活的对象压缩到内存的一端使他们紧凑的排列在一起然后对端边界以外的内存进行回收。回收后已用和未用的内存都各自一边。 优点是解决了内存碎片化的问题相比于复制算法 内存使用率也提高了 缺点仍需要进行局部对象移动一定程度上降低了效率 分代收集算法 分代收集法是目前大部分 JVM 所采用的方法顾名思义是根据对象的存活周期将内存划分为几块。一般包括年轻代、老年代 和 永久代并根据各年代特点分别采用最适当的 GC 算法 老生代的特点是每次垃圾回收时只有少量对象需要被回收 新生代的特点是每次垃圾回收时都有大量垃圾需要被回收 因此可以根据不同区域选择不同的算法 新生代与复制算法 每次垃圾收集都能发现大批对象已死, 只有少量存活. 因此选用复制算法, 只需要付出少量存活对象的复制成本就可以完成收集当然并不是按照11来划分新生代一般是按照eden区s1区s2区 8:1:1 来划分 老年代与标记整理算法 因为老年代对象存活率高、没有额外空间对它进行分配担保, 就必须采用“标记—清理”或“标记—整理” 算法来进行回收, 不必进行内存复制, 且直接腾出空闲内存。因而采用 标记整理算法。