关于YGC时间变长的记录
最近看见很多同事都在讨论一个JVM YGC时间变长的问题,在平时业务开发的过程中,我们经常使用
1 | XStream xs = new XStream();
|
来实现XML和JavaBean之间的相互转换,看看实现就知道在上面的构造函数中不断创建新的classloader出来
1 2 3 4 | public XStream( ReflectionProvider reflectionProvider, Mapper mapper, HierarchicalStreamDriver driver) { this(reflectionProvider, driver, new ClassLoaderReference(new CompositeClassLoader()), mapper, new DefaultConverterLookup(), null); } |
不断创建新的classloader会导致YGC的时间变长。JVM的类加载机制都是双亲委派机制。
假如:AClassLoader->BClassLoader->CClassLoader,现在需要加载X这个类,AClassLoader首先会交给BClassLoader去加载,BClassLoader会交给CClassLoader去加载,如果CClassLoader能加载到,那么X这个类就被加载了。此时在SystemDictionary这个HashTable数据结构中会存储3条记录。
1 2 3 4 5 | X-AClassLoader-X.cls X-BClassLoader-X.cls X-CClassLoader-X.cls 此时SystemDictionary中有三条关于X的加载记录,如果发现任何一条,就认为X已经加载过了。 |
其中AClassLoader和BClassLoader叫做X的出始类加载器。CClassLoader叫做X的定义类加载器。如果不断自定义ClassLoader的话,SystemDictionary中会不断增加K-V记录,这样YGC扫描的范围就越大,YGC耗时就越多。
最后,在使用XStream时,最好别每次都创建一个新的ClassLoader来,减少YGC的时间,提升性能。