静态变量和静态代码块以及变量回收讨论!!!

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()和导致的空指针吗?

5个回答

不会被回收,如果内存不足会报OOM错误,应用基本就瘫了。if (homeApi == null) 线程不安全。

chuwe1
chuwe1 回复chuwe1: m0_37742889的回答是我想要得到的答案!
一年多之前 回复
chuwe1
chuwe1 回复m0_37742889: 兄得 你这个回答 我想要采纳的你回答 然而你不是直接回答的 而是 回复的。采纳不了。。。。
一年多之前 回复
m0_37742889
lickyson 回复chuwe1: 静态成员属于类,静态代码块确实只执行一次,如果静态变量被回收,那么意味着类被卸载,当第二次在调用时JVM需要重新加载类,每次加载类静态成员就会被赋值。你可以看一下<深入理解JVM》的类加载过程
一年多之前 回复
feelcycle_07
默默悟问 不会被回收,因为类一直存在,类里的静态变量都不会被回收。
一年多之前 回复
chuwe1
chuwe1 线程不安全先不考虑,我想知道的是 在静态代码块里面初始化静态变量是否可行?如果静态变量被回收了。照理说静态代码块只会执行一次,第二次调用的时候就不会赋值了。那么还是会出现空指针啊。可是我还是看到很多人这么写,难道不会出现问题?
一年多之前 回复

JVM运行时内存分配情况,在类加载阶段,静态成员被加载到方法区,也叫永久代。JVM类加载过程中有一个叫“类卸载”的过程,只要类没有别卸载,那么它就不会被回收,因为静态成员它是属于类的,不属于对象。
从类加载角度来看,静态变量的初始化,要么定义时直接初始化,要么在静态代码块中初始化,要么在静态方法中初始化,但是不能在非静态方法中初始化。因为静态成员属于类。

静态变量不会被回收,类一开始加载的时候就加载到内存了,一直会存在于jvm的静态区,所以说static修饰的是很占内存的哦,如果不必要就别用静态修饰

类的静态变量和方法都保存在JVM的方法区,而方法区是没有GC的。这种情况下还是内存不足,说明整个程序已经崩溃了。

不会的。
首先,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异常,让程序终止。
此时只能加大堆区内存或者优化程序实现。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!