1.JVM垃圾回收主要实在堆上,那么堆结构是怎样的呢??
2.目前主流的垃圾回收器都会有分代收集,分代收集是什么??
分代收集指的是按新生代垃圾收集(Minor GC)和老年代垃圾收集(Major GC/Full GC);
Full GC比Minor GC慢10倍以上,当老年代内存不足或者显式调用 System.gc()方法时,会触发 Full GC
3.垃圾回收器回收的肯定是无效的对象,那么怎么判断对象是否无效?
有以下两种方法
①引用计数法:
给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加1;当引用失效,计数器就减1;任何时候计数器为0的对象就是不可能再被使用的。
②可达性分析算法:
过一系列的称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,则证明此对象是不可用的
GC Roots:虚拟机栈中引用的对象、java堆类静态属性引用的对象、方法区中常量引用的对象、本地方法栈中JNI引用的对象
4.上文中提到引用计数法,那么引用是什么
JDK1.2之前,Java中引用的定义很传统:如果reference类型的数据存储的数值代表的是另一块内存的起始地址,就称这块内存代表一个引用。
JDK1.2以后,Java对引用的概念进行了扩充,将引用分为强引用、软引用、弱引用、虚引用四种(引用强度逐渐减弱)
①强引用:
比如说通过new创建局部变量 Integer a=new Integer(10);此时垃圾回收器绝不会回收这个对象.
怎么回收强引用对象?
将其置为null,比如Integer a=null;
②软引用
内存空间不足了,就会回收这些对象的内存
// 软引用
String str = new String("abc");
SoftReference<String> softReference = new SoftReference<String>(str);
扩展
软引用可以和一个引用队列(ReferenceQueue)联合使用。如果软引用所引用对象被垃圾回收,JAVA虚拟机就会把这个软引用加入到与之关联的引用队列中。
ReferenceQueue<String> referenceQueue = new ReferenceQueue<>();
String str = new String("abc");
SoftReference<String> softReference = new SoftReference<>(str, referenceQueue);
str = null;
// Notify GC
System.gc();
————————————————
#### 应用场景:
浏览器的后退按钮。按后退时,这个后退时显示的网页内容是重新进行请求还是从缓存中取出呢?这就要看具体的实现策略了。
如果一个网页在浏览结束时就进行内容的回收,则按后退查看前面浏览过的页面时,需要重新构建;
如果将浏览过的网页存储到内存中会造成内存的大量浪费,甚至会造成内存溢出。
这时候就可以使用软引用,很好的解决了实际的问题:
```java
// 获取浏览器对象进行浏览
Browser browser = new Browser();
// 从后台程序加载浏览页面
BrowserPage page = browser.getPage();
// 将浏览完毕的页面置为软引用
SoftReference softReference = new SoftReference(page);
// 回退或者再次浏览此页面时
if(softReference.get() != null) {
// 内存充足,还没有被回收器回收,直接获取缓存
page = softReference.get();
} else {
// 内存不足,软引用的对象已经回收
page = browser.getPage();
// 重新构建软引用
softReference = new SoftReference(page);
}
————————————————
版权声明:本文为CSDN博主「零壹技术栈」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/baidu_22254181/article/details/82555485
③ 弱引用(WeakReference)
如果对象偶尔使用可WeakReference.
弱引用对象不一定会立刻清除因为垃圾回收器是一个优先级很低的线程,不一定会很快发现那些只具有弱引用的对象。
//弱引用
String str = new String("abc");
WeakReference<String> weakReference = new WeakReference<>(str);
//将软引用对象置为Null,下次会回收对象 str=null;
// 弱引用转强引用
String strongReference = weakReference.get();
④虚引用(PhantomReference)
随时都会回收:
虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。
String str = new String("abc");
ReferenceQueue queue = new ReferenceQueue();
// 创建虚引用,要求必须与一个引用队列关联
PhantomReference pr = new PhantomReference(str, queue);
程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要进行垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。
四种引用不同点
强引用:无论什么时候都不会自动回收
软引用:空间不足才会回收对象
弱引用:不是立刻回收而是GC发现后会在下次GC时才会回收对象
虚引用:必须和引用队列(ReferenceQueue)联合使用,本次GC发现立即回收对象
5.上文中都是谈的是对象,那么类呢?类需要满足哪些条件才能被回收
类需要同时满足下面3个条件才能算是 “无用的类” :
①该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。
②加载该类的 ClassLoader 已经被回收。
③该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
6.通过上网知道哪些对象类可以被回收了,那回收有什么策略?
①标记-清除算法
过程:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
缺点:效率不高,且产生大量不连续内存碎片。再分配大对象时,可能无法找到足够的连续内存而导致提前出发一次gc
②复制算法
过程:比如把eden区和survivor from区可用对象复制到survivor to区,然后清理survivor from,eden区
③标记-整理算法
标记可清理对象,然后把可用对象凑在一起,清理掉可用对象凑成的段的外部范围数据
④分代收集算法:
按老年代,新生代分代回收垃圾
在新生代中,每次收集都会有大量对象死去,所以可以选择复制算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清楚”或“标记-整理”算法进行垃圾收集。
引用自https://gitee.com/pig66/java_senior_development_engineer_interview_notes/blob/master/part2-java%E5%9F%BA%E7%A1%80.txt
7.垃圾回收器(七种)
按使用时期范围可分为新生代.老年代,新生代-老年代三种
新生代收集器
一.Serial收集器(最基本、历史最悠久的单线程垃圾收集器,新生代垃圾收集器)
优点:相比其他单线程收集器简单而高效
缺点:单线程运行,运行时会阻碍用户线程.
注意:新生代采用复制算法,老年代采用标记-整理算法。
二.ParNew收集器(新生代垃圾收集器)
相当于Serial收集器的多线程版本.
新生代采用复制算法,老年代采用标记-整理算法。
尽可能缩短垃圾收集时用户线程的停顿时间
三.Parallel Scavenge收集器(针对新生的垃圾收集器)
吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)
优点:并行的多线程回收,以吞吐量优先。高效率使用CPU
注意:Parallel Scavenge收集器侧重于平衡用户停顿时间和垃圾回收时间以达到最大吞吐量效果…
新生代采用复制算法,老年代采用标记-整理算法。
老年代回收器
一.CMS收集器(针对老年代的垃圾收集器)
(1)介绍
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它而非常符合在注重用户体验的应用上使用。
CMS(Concurrent Mark Sweep)收集器是HotSpot虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。
优点:并发收集、低停顿
(2)缺点:
①对CPU资源敏感;(默认分配的垃圾收集线程数为(CPU 数+3)/4,随着 CPU 数量下降,占用 CPU 资源越多,吞吐量越小,并发收集虽然不会暂停用户线程,但因为占用一部分CPU资源,还是会导致应用程序变慢,总吞吐量降低)
②无法处理浮动垃圾;(在并发标记阶段,由于用户程序在运行,那么自然就会有新的垃圾产生,这部分垃圾被标记过后,CMS无法在当次集中处理它们)
③它使用的回收算法-“标记-清除”算法因为没有压缩会导致收集结束时会有大量空间碎片产生。
(3)整个过程分为四个步骤:
初始标记:
并发标记:
重新标记:
并发清除:
二.Serial Old 收集器
Serial Old 收集器是 Serial 的老年代版本,同样是一个单线程收集器,采用标记-整理算法。
三.Parallel Old 收集器
Parallel Old 收集器是 Parallel Scavenge 的老年代版本,是一个多线程收集器,采用标记-整理算法
新生代-老年代垃圾回收器
G1回收器(新生代-老年代垃圾回收器)
(1)介绍:
G1 (Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征.
(2)G1收集器的运作大致分为以下几个步骤:
初始标记
并发标记
最终标记
筛选回收
(3)G1收集器在后台维护了一个优先列表,每次根据允许的收集时间,优先选择回收价值最大的Region(这也就是它的名字Garbage-First的由来)。这种使用Region划分内存空间以及有优先级的区域回收方式,保证了GF收集器在有限时间内可以尽可能高的收集效率(把内存化整为零)。
扩展:CMS收集器和G1收集器的区别
CMS收集器是老年代的收集器,可以配合新生代的Serial和ParNew收集器一起使用;
G1收集器收集范围是老年代和新生代,不需要结合其他收集器使用;
CMS收集器以最小的停顿时间为目标的收集器;
G1收集器可预测垃圾回收的停顿时间
CMS收集器是使用“标记-清除”算法进行的垃圾回收,容易产生内存碎片
G1收集器使用的是“标记-整理”算法,进行了空间整合,降低了内存空间碎片。
————————————————
版权声明:本文为CSDN博主「code_mzh」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/code_mzh/article/details/108609792
表格理解
7.设置参数来使用垃圾回收器
引用自
https://blog.csdn.net/qq_41700030/article/details/109367613命令 意义
-XX:+UseSerialGC 新生代和老年代都用串行收集器
-XX:+UseParNewGC 新生代使用ParNew,老年代使用Serial Old
-XX:+UseParallelGC 新生代使用ParallerGC,老年代使用Serial Old
-XX:+UseParNewGC 新生代使用ParNew,老年代使用Serial Old
-XX:+UseParallerOldGC:新生代使用ParallerGC,老年代使用Parallel Old
-XX:MaxGCPauseMills :垃圾回收最大停顿时间
**-XX:GCTimeRatio:**参数的值应当是一个大于0且小于100的整数,也就是垃圾收集时间占总时间的比率,相当于是吞吐量的倒数。如果把此参数设置为19,那允许的最大GC时间就占总时间的5%(即1/(1+19)),默认值为99,就是允许最大1%(即1/(1+99))的垃圾收集时间。
-XX:+UseAdaptiveSizePolicy:GC自适应的调节策略
-XX:+UseConcMarkSweepGC 新生代使用ParNew,老年代的用CMS