在JavaBean规范中有如下描述:
大意是java默认情况下jdk使用低级的反射机制来分析Bean,为了方便其他人分析bean,java提供了一个内省类Introspector,使用Introspector的getBeanInfo方法可以获取一个封装了bean信息(包括属性和方法)的BeanInfo对象。
Introspector使用不当导致内存泄露的风险
框架几乎都使用了Introspector类来实现灵活性,但是Introspector在获取beanInfo对象时,为了提高性能使用了缓存保存beanInfo:
public static BeanInfo getBeanInfo(Class<?> beanClass)
throws IntrospectionException
{
if (!ReflectUtil.isPackageAccessible(beanClass)) {
return (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo();
}
ThreadGroupContext context = ThreadGroupContext.getContext();
BeanInfo beanInfo;
synchronized (declaredMethodCache) {
beanInfo = context.getBeanInfo(beanClass);
}
if (beanInfo == null) {
beanInfo = new Introspector(beanClass, null, USE_ALL_BEANINFO).getBeanInfo();
synchronized (declaredMethodCache) {
context.putBeanInfo(beanClass, beanInfo);
}
}
return beanInfo;
}
缓存使用ThreadGroupContext——线程组级别共享,类似与ThreadLocal。内部使用WeakHashMap——key为弱引用来保存beanInfo,其中使用class作为key,beanInfo作为value。同时使用WeakIdentityMap保存ThreadGroupContext对象(应该是ThreadGroupContext对象的hash值&