对于GC系统的两个FAQ

    技术2022-07-11  72

    1.当对象存在引用时,是否可能在系统触发GC时被回收?

    可能,要看引用类型 在JAVA中我们可以使用的对象引用方式有四种: 1)强引用:此引用引用的对象,生命力最强。(对象不会被GC) 2)软引用:此引用引用的对象,在内存不足时可能会被GC。 3)弱引用:此引用引用的对象,在GC执行时可能直接会被销毁(即便是内存充足)。 4)虚引用:用的最少,类似没有引用,主要用于记录对象的销毁。(不做演示)

    备注:软引用和弱引用通常会应用在一些缓存产品的设计中。

    下面用代码演示

    //通过JVM参数检测是否触发了GC操作:-XX:+PrintGCDetails class Container{ private Object[] array; public Container(int cap) { this.array=new Container[cap]; } //finalize方法会在对象被回收(GC)之前执行,可以对对象的回收进行监控, // 也可以在对象回收之前进行一些资源释放操作。 @Override protected void finalize() throws Throwable { System.out.println("==finalize()=="); } public class TestGC { public static void main(String[] args) { //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]); // } } }

    当GC系统没有启动时,对象是否可能被回收?

    可能,看对象分配在哪了--堆还是栈上 JAVA中大多数对象都会存储在堆(Heap)中,但对于一些没有逃逸的小对象现在也可能分配在栈上(JVM发展历程中的一种新的优化方式。)。 public class TestGC { 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对对象进行回收。 }
    Processed: 0.009, SQL: 12