Class.forName导致classloader移动到tenured generation?

时间:2012-02-26 04:10:28

标签: java garbage-collection jvm classloader

我见过 Class.forName()导致终身一代被填满。我怀疑JVM内部会将ClassLoader对象移动到tenured generation。例如,以下代码:

public class Test  {
    public static void main(String[] args) throws Exception {
        for (int i=0 ;i<30000;i++) {
            test();
        }
    }
    private static void test() throws Exception {
        MyClassLoader cl = new MyClassLoader();
        Class.forName("java.lang.String", false, cl);
    }
}

public class MyClassLoader extends ClassLoader {}

将输出gc log:

[GC [DefNew:512K-> 64K(576K),0.0041095秒] 512K-> 344K(1984K),0.0042064秒]
[GC [DefNew:576K-> 64K(576K),0.0032096秒] 856K-> 682K(1984K),0.0032937秒] [GC [DefNew:575K-> 63K(576K),0.0032085秒] 1194K-> 1021K(1984K),0.0033686秒]
[GC [DefNew:575K-> 64K(576K),0.0025146秒] 1533K-> 1359K(1984K),0.0026305秒] [GC [DefNew:576K-> 64K(576K),0.0025942秒] [终身:1634K-> 166K(1664K),0.0169541秒] 1871K-> 166K(2240K),0.0197106秒] [GC [DefNew:512K-> 64K(576K),0.0019209秒] 678K-> 505K(1984K),0.0020053秒] [GC [DefNew:576K-> 63K(576K),0.0022846秒] 1017K-> 844K(1984K),0.0024271秒]
[GC [DefNew:575K-> 63K(576K),0.0023358秒] 1356K-> 1182K(1984K),0.0024235秒]
[GC [DefNew:575K-> 64K(576K),0.0025660秒] [终身:1457K-> 166K(1536K),0.0136841秒] 1694K-> 166K(2112K),0.0164004秒]

如果将 Class.forName 更改为 loadClass

private static void test() throws Exception {
    MyClassLoader cl = new MyClassLoader();
    cl.loadClass("java.lang.String");
    //Class.forName("java.lang.String", false, cl);
}

然后gc输出将是:

[GC [DefNew:512K-> 63K(576K),0.0028769秒] 512K-> 138K(1984K),0.0029627秒]
[GC [DefNew:575K-> 0K(576K),0.0009856秒] 650K-> 138K(1984K),0.0010711秒]
[GC [DefNew:512K-> 0K(576K),0.0006255秒] 650K-> 138K(1984K),0.0007062秒]
[GC [DefNew:512K-> 0K(576K),0.0002065秒] 650K-> 138K(1984K),0.0002861秒] [GC [DefNew:512K-> 0K(576K),0.0001936秒] 650K-> 138K(1984K),0.0002674秒] [GC [DefNew:512K-> 0K(576K),0.0002045秒] 650K-> 138K(1984K),0.0002796秒] [GC [DefNew:512K-> 0K(576K),0.0001704秒] 650K-> 138K(1984K),0.0002481秒]
[GC [DefNew:512K-> 0K(576K),0.0002229秒] 650K-> 138K(1984K),0.0003118秒]

在sun jdk1.5和1.6中重现。 jvm(class load和gc)里面发生了什么?

感谢。

1 个答案:

答案 0 :(得分:1)

您的样本太少,无法真正显示GC行为差异的明确原因。首先,您的MyClassLoader实际上不应该加载java.lang.String类,因为它已经存在于引导类加载器中。你的ClassLoader对象(以及Class对象本身)应该一直移动到PermGen空间,所以你对它们在终身代中的猜测有点可疑。

基本上,你的问题“这里JVM内部发生了什么”过于笼统 - 只是读取GC日志输出并没有真正告诉你太多,因为即使看似微不足道的代码差异也可能导致GC模式大不相同,尤其是小测试代码。