Java Secret:加载和卸载静态字段

总览

首先,很自然地假设静态字段具有特殊的生命周期,并且在应用程序的生命周期中一直存在。 您可以假设它们存在于内存中的特殊位置,例如C或类元信息的perm gen中的内存开始。

但是,得知静态字段驻留在堆上,可以具有任意数量的副本并且像其他任何对象一样被GC清除,可能会令人惊讶。

这是在先前的讨论之后得出的; 静态块会被解释吗?

加载静电场

当获得用于链接的类时,它可能不会导致静态块被初始化。

一个简单的例子

public class ShortClassLoadingMain {
    public static void main(String... args) {
        System.out.println("Start");
        Class aClass = AClass.class;
        System.out.println("Loaded");
        String s= AClass.ID;
        System.out.println("Initialised");
    }
}

class AClass {
    static final String ID;
    static {
        System.out.println("AClass: Initialising");
        ID = "ID";
    }
}

版画

Start
Loaded
AClass: Initialising
Initialised

您可以看到,在初始化类之前,您可以获得对类的引用,只有在使用该类时,该类的引用才会被初始化。

加载多个静态场

每个加载类的类加载器都有其自己的静态字段副本。 如果您在两个不同的类加载器中加载一个类,则这些类可以具有具有不同值的静态字段。

卸载静电场

当类的ClassLoader被卸载时,静态字段将被卸载。 执行GC时将卸载该线程,并且线程堆栈中没有强引用。

将这两个概念放在一起

这是一个示例,其中类在初始化消息时以及在其字段完成时打印消息。

class UtilityClass {
    static final String ID = Integer.toHexString(System.identityHashCode(UtilityClass.class));
    private static final Object FINAL = new Object() {
        @Override
        protected void finalize() throws Throwable {
            super.finalize();
            System.out.println(ID + " Finalized.");
        }
    };

    static {
        System.out.println(ID + " Initialising");
    }
}

通过重复加载此类,一次两次

for (int i = 0; i < 2; i++) {
  cl = new CustomClassLoader(url);
  clazz = cl.loadClass(className);
  loadClass(clazz);

  cl = new CustomClassLoader(url);
  clazz = cl.loadClass(className);
  loadClass(clazz);
  triggerGC();
}
triggerGC();

您可以看到这样的输出

1b17a8bd Initialising
2f754ad2 Initialising

-- Starting GC
1b17a8bd Finalized.
-- End of GC

6ac2a132 Initialising
eb166b5 Initialising

-- Starting GC
6ac2a132 Finalized.
2f754ad2 Finalized.
-- End of GC


-- Starting GC
eb166b5 Finalized.
-- End of GC

在此日志中,将首先加载该类的两个副本。 对第一类/类加载器的引用被对第二类/类加载器的引用覆盖。 第一个在GC上清理,第二个保留。 在第二个循环中,又初始化了两个副本。 保留第四个,在GC上清理第二个和第三个。 最后,当不再使用静态字段的第四份副本时,将在GC上清除它们。

编码

第一个示例– ShortClassLoadingMain 第二个示例– LoadAndUnloadMain

参考: Java Secret:Vanilla Java的 JCG合作伙伴 Peter Lawrey 加载和卸载静态字段

相关文章:

翻译自: https://www.javacodegeeks.com/2011/10/java-secret-loading-and-unloading.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值