Jay*_*den 14 java spring hibernate spring-mvc tomcat7
2013/06/07 - 虽然我仍然遇到这个问题,但它仍然只会影响重新部署.自最初的问题发布以来,我们已经升级了一些东西.这是我们的新版本(仍然展示了手头的问题):
<properties>
    <!-- Persistence and Validation-->
    <hibernate.version>4.1.0.Final</hibernate.version>
    <hibernate.jpa.version>1.0.1.Final</hibernate.jpa.version>
    <javax.validation.version>1.0.0.GA</javax.validation.version>
    <querydsl.version>2.2.5</querydsl.version>
    <spring.jpa.version>1.2.0.RELEASE</spring.jpa.version>
    <spring.ldap.version>1.3.1.RELEASE</spring.ldap.version>
    <!-- Spring and Logging -->
    <spring.version>3.1.3.RELEASE</spring.version>
    <spring.security.version>3.1.3.RELEASE</spring.security.version>
    <slf4j.version>1.6.4</slf4j.version>
    <jackson.version>1.9.9</jackson.version>
    <cglib.version>3.0</cglib.version>
</properties>
正如您所看到的,它基本上只是一个Spring Framework bump和Spring(Data)Jpa bump.我们也升级到Tomcat 7.0.39.CGLIB(之前未提及但被包括在内)也被提升至3.0
以下是我试图解决手头问题但没有运气的一些事情:
根据Spring(https://jira.springsource.org/browse/SPR-9274)中未解决的错误报告,重构JPA Persistence配置如下(注意注释):
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { // Important line (notice entityManagerFactory is 'provided/autowired'
    return new JpaTransactionManager(entityManagerFactory);
}
@Bean
public EntityManagerFactory getEntityManagerFactory(DataSource dataSource) { // Important line (notice dataSource is 'provided/autowired'
    LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
    factoryBean.setDataSource(dataSource);
    factoryBean.setPackagesToScan("my.scanned.domain");
    AbstractJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setGenerateDdl(true);
    vendorAdapter.setShowSql(false);
    vendorAdapter.setDatabase(Database.POSTGRESQL);
    vendorAdapter.setDatabasePlatform("org.hibernate.dialect.PostgreSQL82Dialect");
    factoryBean.setJpaVendorAdapter(vendorAdapter);
    Map<String, Object> properties = new HashMap<>();
    properties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
    properties.put( "hibernate.bytecode.provider", "cglib" );   // Suppose to help java pergem space issues with hibernate
    factoryBean.setPersistenceProvider(new HibernatePersistence());
    factoryBean.setJpaPropertyMap(properties);
    factoryBean.setPersistenceUnitName("myPersistenace");
    factoryBean.afterPropertiesSet();
    return factoryBean.getObject(); // Important line
}
@Bean
public PersistenceExceptionTranslator getHibernateExceptionTranslator() { // Required
    return new HibernateExceptionTranslator();
}
@Bean
public DataSource getDataSource() {
    JndiDataSourceLookup lookup = new JndiDataSourceLookup();
    DataSource dataSource = lookup.getDataSource("java:comp/env/jdbc/myLookup");
    lookup = null;
    return dataSource;
}
在这一点上,我已经没有想法了.
我也尝试使用此作为起点学习堆分析(http://cdivilly.wordpress.com/2012/04/23/permgen-memory-leak/).我可以找到没有清理的类加载器,我可以看到它仍然引用了所有与Spring相关的类.我也尝试过搜索,org.springframework.core.NamedThreadLocal在运行ThreadImmolator,Thread Leak Preventor以及我在上面尝试的其他"重手解决方案"之后,我仍然可以看到它们出现在堆中.
也许以上信息可能会对某些人有所帮助,但我会继续用新信息或如果我解决问题来重新审视此SO.
应用程序在生产服务器上连续几天没有运行问题,但是当我执行部署更新时,Tomcat Manager程序会抱怨泄漏(如果我单击查找泄漏).如果我执行6-10部署,最终Tomcat内存不足,出现PermGen内存错误,我需要重新启动Tomcat服务,一切都恢复正常.
当我在本地运行/调试应用程序并执行一些需要通过Jpa/Hibernate访问的操作(即,我登录或从JpaRepository请求List)然后关闭应用程序时,我在Tomcat的调试输出中收到以下消息:
2012年10月3日下午2:55:13 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks严重:Web应用程序[/]使用[org.springframework.core.NamedThreadLocal]类型的键创建了一个ThreadLocal(值[Transactional resources] )和类型为[java.util.HashMap]的值(value [{public abstract java.lang.Object org.springframework.data.repository.CrudRepository.findOne(java.io.Serializable)= java.lang.Object@842e211 }]但是在Web应用程序停止时无法删除它.线程将随着时间的推移而更新,以避免可能的内存泄漏.
2012年10月3日下午2:55:13 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks严重:Web应用程序[/]使用[org.springframework.core.NamedThreadLocal]类型的键创建了一个ThreadLocal(值[Transactional resources] )和类型为[java.util.HashMap]的值(value [{public abstract java.util.List org.springframework.data.jpa.repository.JpaRepository.findAll()= java.lang.Object@842e211}])但是在Web应用程序停止时无法将其删除.线程将随着时间的推移而更新,以避免可能的内存泄漏.
2012年10月3日下午2:55:13 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks严重:Web应用程序[/]使用[org.springframework.core.NamedThreadLocal]类型的键创建了一个ThreadLocal(值[Transactional resources] )和类型为[java.util.HashMap]的值(value [{public abstract java.lang.Iterable org.springframework.data.querydsl.QueryDslPredicateExecutor.findAll(com.mysema.query.types.Predicate)= java.lang .Object @ 842e211}])但是在Web应用程序停止时无法将其删除.线程将随着时间的推移而更新,以避免可能的内存泄漏.
2012年10月3日下午2:55:13 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks严重:Web应用程序[/]使用[org.springframework.core.NamedThreadLocal]类型的键创建了一个ThreadLocal(值[Transactional resources] )和类型[java.util.HashMap]的值(值[{public abstract data.domain.UserAccount UserAccountRepository.findByUserName(java.lang.String)= java.lang.Object@842e211}])但无法删除它当Web应用程序停止时.线程将随着时间的推移而更新,以避免可能的内存泄漏.
等等
Spring是通过注释配置的,我也使用Postgres 8.4作为数据库后端.
JPA是通过注释配置的(jpa-repository-context.xml只是说要查找这个类):
@Configuration
@EnableTransactionManagement
@ImportResource( "classpath*:*jpa-repository-context.xml" )
@ComponentScan( basePackages = { "data.repository" } )
public class PersistenceJpaConfig
{
    @Bean
        public LocalContainerEntityManagerFactoryBean entityManagerFactory()
        {
            LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
            factoryBean.setDataSource( dataSource() );
            factoryBean.setPackagesToScan( new String[] { "data.domain" } );
            // Setup vendor specific information. This will depend on the chosen DatabaseType
            HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
            vendorAdapter.setGenerateDdl( true );
            vendorAdapter.setShowSql( false );
            vendorAdapter.setDatabasePlatform( "org.hibernate.dialect.PostgreSQL82Dialect" );
            factoryBean.setJpaVendorAdapter( vendorAdapter );
            Map<String, Object> properties = new HashMap<String, Object>();
            properties.put( "hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy" );
            factoryBean.setJpaPropertyMap( properties );
            return  factoryBean;
        }
        @Bean
        public DataSource dataSource()
        {
            JndiDataSourceLookup lookup = new JndiDataSourceLookup();
            DataSource dataSource;
            dataSource = lookup.getDataSource( "java:comp/env/jdbc/postgres" );
            return dataSource;
        }
        @Bean
        public PlatformTransactionManager transactionManager()
        {
            JpaTransactionManager transactionManager = new JpaTransactionManager();
            transactionManager.setEntityManagerFactory( entityManagerFactory().getObject() );
            return transactionManager;
        }
}
示例存储库:
public interface UserAccountRepository extends JpaRepository<UserAccount, Long>, QueryDslPredicateExecutor<UserAccount> {
}
我的所有存储库都是通过Service类访问的,该类在Spring中注册为@Component.这样做是为了从Spring控制器中删除存储库访问:
@Component
public class UserAccountService {
    @Autowired
    private UserAccountRepository userAccountRepository;
    public List<UserAccount> getUserAccounts() {
        return userAccountRepository.findAll();
    }
    ...
}
以下是Maven的pom.xml中使用的各种组件的版本:
<properties>
        <!-- Persistence and Validation-->
        <hibernate.version>4.1.0.Final</hibernate.version>
        <hibernate.jpa.version>1.0.1.Final</hibernate.jpa.version>
        <javax.validation.version>1.0.0.GA</javax.validation.version>
        <querydsl.version>2.2.5</querydsl.version>
        <spring.jpa.version>1.1.0.RELEASE</spring.jpa.version>
        <!-- Spring and Logging -->
        <spring.version>3.1.2.RELEASE</spring.version>
        <spring.security.version>3.1.2.RELEASE</spring.security.version>
        <slf4j.version>1.6.4</slf4j.version>
        <jackson.version>1.9.9</jackson.version>
        <!-- Testing Suites -->
        <selenium.version>2.24.1</selenium.version>
</properties>
我真的没有解决这个问题的想法了.
我认为您可能同时发生两种泄漏。Spring 警告您有关正常的“堆”内存泄漏。这还没有给你带来问题,因为......你的重新部署也会导致过度的 PermGen 使用,而这个问题首先会困扰你。有关第二种泄漏的信息,请参阅处理“java.lang.OutOfMemoryError: PermGen space”错误 [感谢 duffymo]
[更新]
既然你说上面链接中的建议没有帮助,我能想到的唯一其他建议是:
尝试 -XX:MaxPermSize=256m 如果它仍然存在,请尝试 -XX:MaxPermSize=512m
最终的超级暴力方法是逐渐从应用程序中删除某些内容,直到问题消失。这将帮助您缩小范围,确定是代码问题还是 Spring、Hibernate 等中的错误
| 归档时间: | 
 | 
| 查看次数: | 9752 次 | 
| 最近记录: |