精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2012-04-13
在项目开发过程中,遇到一个jvm 不能回收内存的问题 ,导致到最后old区占100%,服务器一直超时响应很慢,最后自动重启。。。。。
通过jstack 查看得到 线程有6-700个线程全部处于阻塞状态:BLOCKED
"resin-tcp-connection-*:8080-2401" daemon prio=10 tid=0x00002aab3df66000 nid=0x1693 waiting for monitor entry [0x00002aac50f09000] java.lang.Thread.State: BLOCKED (on object monitor) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:180) - waiting to lock <0x00002aaabe5fd790> (a java.util.concurrent.ConcurrentHashMap) at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:415) at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:223) at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:303) at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:297) at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:941) at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:224) at org.springframework.beans.factory.BeanFactoryUtils.beanOfTypeIncludingAncestors(BeanFactoryUtils.java:309)
具体错误见上面,查看了一下spring的源代码
protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { synchronized (this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory singletonFactory = (ObjectFactory) this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject != NULL_OBJECT ? singletonObject : null); }
网上这是spring的一个缺陷,但直到最新版本也没有见修复。具体见如URL: https://jira.springsource.org/browse/SPR-6870
Spring中 获取一个spring容器管理的Bean可以通过 getBeanByName or getBeanByType 其中能过前者获取到的beanspring是有加缓存的,而getBeanByType 每次都是重新去生成(其实我也没去深究过他的源码)
不过我做了一个测试:
long startTime = System.currentTimeMillis(); User user3 = null; for(int i=0; i<100000; i++) { user3 = BeanFactory.getBean("user"); user3.print(); } long endTime = System.currentTimeMillis(); System.out.println("getBeanByName spend time :" + (endTime - startTime) + "ms"); System.out.println("current momory:" + SprintTest.getUsedMemory()); User user4 = null; for(int i=0; i<100000; i++) { user4 = BeanFactory.getBean(User.class); user4.print(); } long end = System.currentTimeMillis(); System.out.println("getBeanBytype spend time :" + (end - endTime) + "ms"); System.out.println("current momory:" + SprintTest.getUsedMemory());
Factory方法:
@SuppressWarnings("unchecked") public static <T> T getBean(final String name) { return (T) ctx.getBean(name); } public static <T> T getBean(final Class<T> clazz) { return clazz.cast(BeanFactoryUtils.beanOfTypeIncludingAncestors(ctx, clazz)); }
结果如下:
getBeanByName spend time :86ms current momory:899560 getBeanBytype spend time :773ms current momory:1576440
很震撼。。。。时间直接是数量级的差别,空间也有很大的差别。 建议大家尽量少使用getBeanByType 吧,如果一定需要用的话,可以通过人为的加缓存来解决这种性能问题 ,尽量少使用避免这种BUG出现。
此外还引出另外一个问题 ,有的同学在Util里面引用一些Sprint管理的类,一般Util的方法都是静态的,他本身不在Sprint容器的管理范围之内,那怎么解决这个方法呢,可以用Sprng工厂去获得bean
public class BeanFactory implements ApplicationContextAware { private static ApplicationContext ctx; private static BeanFactory singleton; public BeanFactory() { singleton = this; } public static BeanFactory getInstance(){ return singleton; } public void setApplicationContext(ApplicationContext ctx) throws BeansException { BeanFactory.ctx = ctx; } @Autowired private User user; public User getUser() { return user; } @SuppressWarnings("unchecked") public static <T> T getBean(final String name) { return (T) ctx.getBean(name); } public static <T> T getBean(final Class<T> clazz) { return clazz.cast(BeanFactoryUtils.beanOfTypeIncludingAncestors(ctx, clazz)); }
可以通过BeanFactory.getInstance().getBean("name") 的方法去实现
如果是在Spring管理的bean里面调用别的bean的话就简了 或者你通过Spring 的@Autowired注入,或者set 注入 都可以。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
浏览 1779 次