Hi Liquan,<div><br></div><div>That&#39;s because Class.forName() will keep a reference to your class loader in the SystemDictionary (for being an initiating loader of the class, in your example &quot;java.lang.String&quot;), whereas ClassLoader.loadClass() won&#39;t.</div>
<div><br></div><div>SystemDictionary is the place where HotSpot VM keeps track of all currently loaded classes, with the mapping of:</div><div>(class name, class loader) =&gt; class</div><div>The &quot;class loader&quot; part includes both defining class loaders and initiating class loaders.</div>
<div><br></div><div>During minor GC:</div><div>The whole SystemDictionary is a part of the root set in a minor GC. Class unloading doesn&#39;t happen. The class loaders referenced by the SystemDictionary aren&#39;t collected, either.</div>
<div>So in you example, the loader are all kept alive&nbsp;with&nbsp;Class.forName().</div><div><br></div><div>[GC [DefNew: 576K-&gt;64K(576K), 0.0025942 secs][Tenured: 1634K-&gt;166K(1664K), 0.0169541 secs] 1871K-&gt;166K(2240K), 0.0197106 secs]</div>
<div><br></div><div>This kind of GC log shows that a collection started out as a minor GC, but failed to allocate enough space in the old generation to promotion surviving objects, so it bailed out and fell back to a full GC which collects the whole GC heap. This kind of fallback doesn&#39;t print &quot;[Full GC&quot; in the GC logs, so it&#39;s kind of tricky to tell if you don&#39;t know the gory details.</div>
<div>You could turn on -XX:+PrintPromotionFailure to see promotion failure in action.</div><div><br></div><div>A full GC will collect dead class loaders and unload unused classes. So your example won&#39;t get an OOME just for filling up the old generation with class loaders.</div>
<div><br></div><div>Just to be clear: this behavior wouldn&#39;t be considered a bug in the VM. You&#39;ll have to take care of class loading more carefully in your application.</div><div><br></div><div>HTH,</div><div>- Kris<br>
<br><div class="gmail_quote">2012/2/27 浩明 <span dir="ltr">&lt;<a href="mailto:liquan.liu@alipay.com">liquan.liu@alipay.com</a>&gt;</span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi all,<br>
<br>
I have seen Class.forName() causes the tenured generation got filled with custom ClassLoader objects. I suspect something JVM done internally will move the ClassLoader objects to tenured generation. For example, the following code:<br>

========================<br>
public class Test &nbsp;{<br>
 &nbsp; public static void main(String[] args) throws Exception {<br>
 &nbsp; &nbsp; for (int i=0 ;i&lt;30000;i++) {<br>
 &nbsp; &nbsp; &nbsp; &nbsp; test();<br>
 &nbsp; &nbsp; }<br>
 &nbsp; }<br>
 &nbsp; private static void test() throws Exception {<br>
 &nbsp; &nbsp; MyClassLoader mcl = new MyClassLoader();<br>
 &nbsp; &nbsp; Class.forName(&quot;java.lang.String&quot;, false, mcl);<br>
 &nbsp; }<br>
}<br>
<br>
public class MyClassLoader extends ClassLoader {}<br>
=========================<br>
will output gc log:<br>
<br>
[GC [DefNew: 512K-&gt;64K(576K), 0.0041095 secs] 512K-&gt;344K(1984K), 0.0042064 secs]<br>
[GC [DefNew: 576K-&gt;64K(576K), 0.0032096 secs] 856K-&gt;682K(1984K), 0.0032937 secs]<br>
[GC [DefNew: 575K-&gt;63K(576K), 0.0032085 secs] 1194K-&gt;1021K(1984K), 0.0033686 secs]<br>
[GC [DefNew: 575K-&gt;64K(576K), 0.0025146 secs] 1533K-&gt;1359K(1984K), 0.0026305 secs]<br>
[GC [DefNew: 576K-&gt;64K(576K), 0.0025942 secs][Tenured: 1634K-&gt;166K(1664K), 0.0169541 secs] 1871K-&gt;166K(2240K), 0.0197106 secs]<br>
[GC [DefNew: 512K-&gt;64K(576K), 0.0019209 secs] 678K-&gt;505K(1984K), 0.0020053 secs]<br>
[GC [DefNew: 576K-&gt;63K(576K), 0.0022846 secs] 1017K-&gt;844K(1984K), 0.0024271 secs]<br>
[GC [DefNew: 575K-&gt;63K(576K), 0.0023358 secs] 1356K-&gt;1182K(1984K), 0.0024235 secs]<br>
[GC [DefNew: 575K-&gt;64K(576K), 0.0025660 secs][Tenured: 1457K-&gt;166K(1536K), 0.0136841 secs] 1694K-&gt;166K(2112K), 0.0164004 secs]<br>
<br>
<br>
If change the Class.forName to loadClass:<br>
========================<br>
private static void test() throws Exception {<br>
 &nbsp; &nbsp;MyClassLoader mcl = new MyClassLoader();<br>
 &nbsp; &nbsp;mcl.loadClass(&quot;java.lang.String&quot;);<br>
}<br>
========================<br>
then gc log will be:<br>
<br>
[GC [DefNew: 512K-&gt;63K(576K), 0.0028769 secs] 512K-&gt;138K(1984K), 0.0029627 secs]<br>
[GC [DefNew: 575K-&gt;0K(576K), 0.0009856 secs] 650K-&gt;138K(1984K), 0.0010711 secs]<br>
[GC [DefNew: 512K-&gt;0K(576K), 0.0006255 secs] 650K-&gt;138K(1984K), 0.0007062 secs]<br>
[GC [DefNew: 512K-&gt;0K(576K), 0.0002065 secs] 650K-&gt;138K(1984K), 0.0002861 secs]<br>
[GC [DefNew: 512K-&gt;0K(576K), 0.0001936 secs] 650K-&gt;138K(1984K), 0.0002674 secs]<br>
[GC [DefNew: 512K-&gt;0K(576K), 0.0002045 secs] 650K-&gt;138K(1984K), 0.0002796 secs]<br>
[GC [DefNew: 512K-&gt;0K(576K), 0.0001704 secs] 650K-&gt;138K(1984K), 0.0002481 secs]<br>
[GC [DefNew: 512K-&gt;0K(576K), 0.0002229 secs] 650K-&gt;138K(1984K), 0.0003118 secs]<br>
<br>
Reproduced in both jdk1.5 and 1.6.<br>
<br>
Can someone enlight me what&#39;s happening inside jvm (regarding class load and gc) ?<br>
<br>
Thanks.<br>
<br>
________________________________<br>
<br>
This email (including any attachments) is confidential and may be legally privileged. If you received this email in error, please delete it immediately and do not copy it or use it for any purpose or disclose its contents to any other person. Thank you.<br>

<br>
本电邮(包括任何附件)可能含有机密资料并受法律保护。如您不是正确的收件人,请您立即删除本邮件。请不要将本电邮进行复制并用作任何其他用途、或透露本邮件之内容。谢谢。<br>
<br>_______________________________________________<br>
hotspot-gc-use mailing list<br>
<a href="mailto:hotspot-gc-use@openjdk.java.net">hotspot-gc-use@openjdk.java.net</a><br>
<a href="http://mail.openjdk.java.net/mailman/listinfo/hotspot-gc-use" target="_blank">http://mail.openjdk.java.net/mailman/listinfo/hotspot-gc-use</a><br>
<br></blockquote></div><br></div>