Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
A CU faces with memory leak. This seems to occur because Introspector.getBeanInfo() does not release some resources. CONFIGURATION: JDK: 6u15(and later)/JDK7 OS : WindowsXP(SP3, Japanese) INVESTIGATION: The following source portion is extracted from JDK6u23. The program accesses to AppContext at line#162. If this access is the first time, AppContext.<clinit> starts to run. --------------------------------------------------------------------------------------------- <j2se/src/share/classes/java/beans/Introspector.java> 150 public static BeanInfo getBeanInfo(Class<?> beanClass) 151 throws IntrospectionException 152 { 153 if (!ReflectUtil.isPackageAccessible(beanClass)) { 154 return (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo(); 155 } 156 Map<Class<?>, BeanInfo> beanInfoCache; 157 BeanInfo beanInfo; 158 synchronized (BEANINFO_CACHE) { 159 beanInfoCache = (Map<Class<?>, BeanInfo>) AppContext.getAppContext().get(BEANINFO_CACHE); 160 if (beanInfoCache == null) { 161 beanInfoCache = new WeakHashMap<Class<?>, BeanInfo>(); 162 AppContext.getAppContext().put(BEANINFO_CACHE, beanInfoCache); 163 } 164 beanInfo = beanInfoCache.get(beanClass); 165 } 166 if (beanInfo == null) { 167 beanInfo = new Introspector(beanClass, null, USE_ALL_BEANINFO).getBeanInfo(); 168 synchronized (BEANINFO_CACHE) { 169 beanInfoCache.put(beanClass, beanInfo); 170 } 171 } 172 return beanInfo; 173 } --------------------------------------------------------------------------------------------- In AppContext.<clinit>, AppContext instance is created and the value of Thread.currentThread().getContextClassLoader() is set to the field of contextClassLoader at line#227. The referent to the contextClassLoader never be broken. That seems to result in memory leak. --------------------------------------------------------------------------------------------- <j2se/src/share/classes/sun/awt/AppContext.java> 221 AppContext(ThreadGroup threadGroup) { 222 numAppContexts++; 223 224 this.threadGroup = threadGroup; 225 threadGroup2appContext.put(threadGroup, this); 226 227 this.contextClassLoader = 228 (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() { 229 public Object run() { 230 return Thread.currentThread().getContextClassLoader(); 231 } 232 }); 233 } --------------------------------------------------------------------------------------------- SAMPLE PROGRAM: A small program which simulates the above mentioned behavior. Please unfoled the TP.zip and invoke "java Test" in jdk6ux. If the referent is broken correctly, the message "OK: MyClassLoader is not Reference." appears and this is expected. On tje other hands, in jdk6u15 and later, "NG: MyClassLoader is Reference." will appear. This shows that the referent still remains under the situation when that should be broken. In this test case, the impact is very small. However, in actual applications like appli. servers, such small leak piles up for long application's run. That result in serious memory exhaustion. Please see the comment section for a little bit more comment by the CU.
|