参考《深入理解JVM&G1CG》---周明耀,这本书讲的比较浅,如果需要深入了解,还得增加资料。
类加载遵循“双亲委派”一般由父加载器ClassLoader进行加载,父加载器加载不了的才让子加载器加载。不然不同的加载器加载的类,是不一样的,使用equals方法可能会得到false。比如String使用ClassLoader,若使用自己定的加载器加载,可能可以做一点手脚,大家都会中招。还是用父类加载器比较安全。
加载器包括
- 启动类加载器(Bootstrap ClassLoader):C++实现,在java里无法获取,负责加载/lib下的类。
- 扩展类加载器(Extension ClassLoader): Java实现,可以在java里获取,负责加载/lib/ext下的类。
- 系统类加载器/应用程序类加载器(Application ClassLoader):是与我们接触对多的类加载器,我们写的代码默认就是由它来加载,ClassLoader.getSystemClassLoader返回的就是它。
- 自定义加载器。1 - 4 ,父 - 子。
加载、验证、准备、解析、初始化、使用、销毁。
解析:由符号引用变为直接引用。https://blog.csdn.net/chenge_j/article/details/72677766
java对象的引用方式有以下四种:
强引用,变量=值 这种方式,GC不会回收,宁愿选择OOM,也不回收这个对象。
String str = "hello java";
Object object = new Object();
因为GC算法是,从root能索引到的对象就不会被回收。但是当这个对象用完了,如一个线程结束了,就不会被root索引到,可进行回收了。
软引用,可以避免强引用带来的OOM,GC的时候,如果空间足,不会回收这个对象,如果不足,进行回收。
SoftReference<String> sr = new SoftReference<String>(new String("hello"));
System.out.println(sr.get()); System.gc(); //通知JVM的gc进行垃圾回收
System.out.println(sr.get()); 存在
弱引用,同样可以避免OOM,GC的时候,不论空间足不足,都会进行回收。
WeakReference<String> wr = new WeakReference<String>(new String("hello"));
System.out.println(wr.get());
System.gc(); //通知JVM的gc进行垃圾回收
System.out.println(wr.get()); 不存在
虚引用,通过PhantomReference,幽灵引用,没有存在感,不晓得有什么卵用。
ReferenceQueue<String> queue = new ReferenceQueue<String>();
PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue);
System.out.println(pr.get()); 不存在
判断对象是否存活:引用计数、可达性分析
垃圾回收算法:标记-清除、标记-压缩、复制、分代回收。
-XX:+HeapDumpOnOutOfMemoryError系统出现oom的时候,生产dump文件。也可以用jmap命令。
jvm内存模型为:计数器、本地方法栈、栈、堆、方法区;堆中分为新生代、老年代;方法区以前成为永久代(jdk8被淘汰)
收集器名称 | 类型 | 用途 | 开启 | |
Serial | 吞吐量优先 | Serial | 年轻代、复制算法、STW | -XX: +UseSerialGC |
Serial Old | 老年代、标记压缩、STW | |||
ParNew | 吞吐量优先 | ParNew | Serial的多线程版本 | -XX:+UseParallelGC -XX:+UseParNewGC(可以配合CMS) 年轻代使用并行收集器 老年代使用串行收集器 |
Parallel | 吞吐量优先 | 年轻代:标记复制 老年代:标记压缩
吞吐量优先 | -XX:+UseParallelOldGC 年轻代、老年代都使并行收集器 | |
CMS | 低延时优先 设置停顿时间 | 老年代专用:标记清除 初始标记、 并发标记、 再次标记、 并发清除 | -XX:+UseConcMarkSweepG | |
G1 | 低延时优先 设置停顿时间 |
Serial、ParNew都是GC利用单核或者多核,全占CPU,与应用无关。
Parallel可以关注吞吐量,与应用并行进行。
CMS处理GC的方法可以视为Parallel的进化版
CMS相关:老年代专用回收器。它的初始标记会带来短暂STW,因为只是一个初步的标记,不会暂停太久。由于要处理第二阶段并发标记中业务线程创建的无用对象,接下来的再次标记这个阶段会STW时间长一点。还有碎片产生。为了应对碎片的产生,配置一个参数-XX:+UseCMS-CompactAtFullCollection用来在每次FullGC之后进行碎片整理,但是会带来较大的停顿,则可以配置另一个参数-XX:CMSFullGCs-BeforeCompaction限制多少次FullGC之后进行一次碎片整理。
CMS提供-XX:CMSlnitiatingOccupanyFraction参数来决定老年代已用空间占到老年代多少比例(68%jdk6>Verson, 92%jdk6<Verson)之后进行回收操作。其他的收集器(除了G1),似乎没有这个选项。也就是,这个参数可以减少FullGC的触发次数(未雨绸缪)。但没有设置停留时间的选项。
G1相关:jdk1.7正式投入,jdk9默认。很重视老年代,如果老年代占到了整个堆大小的百分之多少,就会进行回收。Region大小为1M-32M大小之间,2的倍数,这样在堆大小既定的情况下,就可以计算出Region数量了。如果来了大对象,计算x个连续的Region可以放下对象即可,如果没有这个连续的x个,则进行一次FullGC。
串行收集器、并行收集器(吞吐量优先,最短的暂停时间处理完GC)、并发收集器(响应时间优先,与程序并发同行CMS)