JVM GC 系统 面试问题
市场常见GC算法?(不限于java平台)JVM中常见GC算法?(不同规范的实现,算法不相同)JVM规范的实现HotSpot虚拟机有什么GC算法的应用?具体应用场景有什么不同。FAQ:
1.当对象存在引用时,是否可能在系统触发GC时被回收?可能,要看引用类型? 2. 当GC系统没有启动,对象是否可能被回收? 3.当GC系统触发时,假如对象要被销毁了会执行finalize方法吗?会的。
1)当对象存在引用时,是否可能在系统触发GC时被回收? 答: 1. 可能,要看引用类型; 2. 强引用不会,软引用在内存不足时会,弱引用会被回收,虚也会。 3. 在JAVA中我们可以使用的对象引用方式有四种: 1)强引用:此引用引用的对象,生命力最强。(对象不会被GC) 2)软引用:此引用引用的对象,在内存不足时可能会被GC。 3)弱引用:此引用引用的对象,在GC执行时可能直接会被销毁(即便是内存充足)。 4)虚引用:用的最少,类似没有引用,主要用于记录对象的销毁。---了解 ***说明:软引用和弱引用通常会应用在一些缓存产品的设计中。***代码案例
package com.cy.java.jvm.gc; import java.lang.ref.WeakReference; /** * FAQ: * 1)当对象存在引用时,是否可能在系统触发GC时被回收?可能,要看引用类型? * 2)当GC系统触发时,假如对象要被销毁了会执行finalize方法吗?会的。 * * JVM GC 系统 * 1)市场常见GC算法?(不限于java平台) * 2)JVM中常见GC算法?(不同规范的实现,算法不相同) * 3)JVM规范的实现HotSpot虚拟机有什么GC算法的应用?具体应用场景有什么不同。 */ class Container{ private Object[] array; public Container(int cap) { this.array=new Container[cap]; } //.... @Override protected void finalize() throws Throwable { System.out.println("==finalize()=="); } } public class TestGC02 { public static void main(String[] args) { doMethod01(); } /** * 在JAVA中我们可以使用的对象引用方式有四种: * 1)强引用:此引用引用的对象,生命力最强。(对象不会被GC) * 2)软引用:此引用引用的对象,在内存不足时可能会被GC。 * 3)弱引用:此引用引用的对象,在GC执行时可能直接会被销毁(即便是内存充足)。 * 4)虚引用:用的最少,类似没有引用,主要用于记录对象的销毁。---了解 * * 说明:软引用和弱引用通常会应用在一些缓存产品的设计中。 */ private static void doMethod01() { //1.强引用 Container c1=new Container(100);//c1就是强引用 c1=null;//此时c1指向的Container对象不可达(也就是说JVM访问不到了) //2.软引用 SoftReference<Container> c2=new SoftReference<Container>(new Container(20)); Container cc=c2.get();//这种写发是又将软引用转换为了强引用。不推荐 System.out.println(c2.get());//通过软引用获取和操作对象 //3.弱引用 WeakReference<Container> c3=new WeakReference<Container>(new Container(100)); System.out.println(c3.get()); //手动GC System.gc();//GC启动以后,GC系统会对内存中的对象进行可达性分析。访问不到则进行标记。 //自动GC(通过JVM参数进行分析) // List<byte[]> list=new ArrayList<>(); // for(int i=0;i<100000;i++) { // list.add(new byte[1024*1024]); // } } } 2)当GC系统没有启动,对象是否可能被回收? 答: 1. 可能,要看对象分配在哪,栈中不用GC,直接回收 2. Java中大多数对象都会存储在堆(heap)中,但对于一些没有逃逸的小对象,现在也可能分配在栈上(JVM发展历程中的一种新的优化方式), 3. 小对象,未逃逸(方法外界没有引用指向方法内对象),栈上直接销毁,不用GC 4. 小对象,逃逸(方法外界有引用指向方法内对象),分配在堆上 JDK8中,默认打开逃逸分析选项,希望未逃逸的小对象分配在栈上,这样可以避免启动GC进行回收对象。 总结: 小对象,未逃逸,栈上分配(方法调用结束,对象销毁,不需要借助GC); 小对象,已逃逸,堆上分配(对象回收需要借用GC系统);代码案例:
package com.cy.java.jvm.gc; /** * 当GC系统没有启动时,对象是否可能被回收?可能,看你对象分配在哪了? * 说明:JAVA中大多数对象都会存储在堆(Heap)中,但对于一些没有逃逸的小对象 * 现在也可能分配在栈上(JVM发展历程中的一种新的优化方式。)。 */ public class TestGC03 { //-XX:+PrintGCDetails public static void main(String[] args) { for(int i=0;i<100000000;i++) { doMethod01(); } } static byte[] b2; static void doMethod01() { //小对象,未逃逸,栈上分配,栈上分配对象的对象,方法调用结束,对象销毁。 //byte[] b1=new byte[1024*1024]; //小对象,未逃逸(方法外界没有引用指向此对象),可以直接分配在栈上 //小对象,已逃逸,堆上分配,对象回收需要借助GC系统。 b2=new byte[1];//小对象,但逃逸了(方法外部有引用指向此对象),对象分配在堆上 } //JDK8中默认会打开逃逸分析选项,希望未逃逸的小对象分配在栈上,这样可以避免启动GC对对象进行回收。 }