public class NetWork {
private static Retrofit retrofit;
static {
retrofit = new Retrofit.Builder()
.client(builder.build())
.baseUrl("...")
.build();
}
private NetWork() {}
private static HomeApi homeApi;
public static HomeApi homeApi() {
if (homeApi == null) {
homeApi = retrofit.create(HomeApi.class);
}
return homeApi;
}
}
这样写会出现因为内存不足导致retrofit和homeApi两个对象一起被回收。而在此调用NetWork.homeApi()和导致的空指针吗?
不会被回收,如果内存不足会报OOM错误,应用基本就瘫了。if (homeApi == null) 线程不安全。
不会的。
首先,static变量在方法区,不在堆区,平时说的GC指的是堆区的GC。
方法区GC和堆区GC不一样,方法区GC是卸载类,存在以下几个前提:
1、该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例。
2、加载该类的ClassLoader已经被回收。
3、该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。
还未执行homeApi = retrofit.create(HomeApi.class);时,不满足卸载类的条件,所以不会收回空间。
即使方法区没空间了,也不会回收将要被使用的空间,会报错Out of Memory,解决办法是调大永久代空间。
不会随便回收空间的。
另外,哪怕homeApi和retrofit在堆区,也不会回回收。
如果没空间就回收这些还将要使用的变量,那所有的java程序都不要运行了。
GC回收的是不会被使用的空间。堆区实在没空间了也不会回收,JVM会报错Out of Memory异常,让程序终止。
此时只能加大堆区内存或者优化程序实现。
静态变量不会被回收,类一开始加载的时候就加载到内存了,一直会存在于jvm的静态区,所以说static修饰的是很占内存的哦,如果不必要就别用静态修饰
JVM运行时内存分配情况,在类加载阶段,静态成员被加载到方法区,也叫永久代。JVM类加载过程中有一个叫“类卸载”的过程,只要类没有别卸载,那么它就不会被回收,因为静态成员它是属于类的,不属于对象。
从类加载角度来看,静态变量的初始化,要么定义时直接初始化,要么在静态代码块中初始化,要么在静态方法中初始化,但是不能在非静态方法中初始化。因为静态成员属于类。
类的静态变量和方法都保存在JVM的方法区,而方法区是没有GC的。这种情况下还是内存不足,说明整个程序已经崩溃了。