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对对象进行回收。
}