gpt4 book ai didi

mysql - 停止/重新部署时 Tomcat 7+ 内存泄漏。 Spring Data、JPA、Hibernate、MySQL

转载 作者:可可西里 更新时间:2023-11-01 06:30:01 25 4
gpt4 key购买 nike

我在停止/重新部署应用程序时遇到 tomcat 内存泄漏问题。它说 以下 Web 应用程序已停止(重新加载、取消部署),但它们的之前运行的类仍然加载在内存中,从而导致内存泄漏(使用分析器确认):/test-1.0-SNAPSHOT

MySQL 连接器驱动程序位于 Tomcat/lib 文件夹中。我可以在两者中重现此问题:Tomcat 7/8。还尝试使用“net.sourceforge.jtds.*”驱动程序的 MS SQL 数据库,但没有帮助。

请在下面找到项目文件。项目仅在数据库中创建 1 个表。

build.gradle

group 'com.test'
version '1.0-SNAPSHOT'

apply plugin: 'java'
apply plugin: 'war'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.hibernate', name: 'hibernate-entitymanager', version: '5.2.10.Final'
compile group: 'org.springframework.data', name: 'spring-data-jpa', version: '1.11.4.RELEASE'
compile group: 'org.springframework', name: 'spring-webmvc', version: '4.3.9.RELEASE'
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
providedCompile group: 'mysql', name: 'mysql-connector-java', version: '5.1.6'
compile group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4'
}

ApplicationConfig.java

@Configuration
@Import({JPAConfiguration.class})
@EnableWebMvc
public class ApplicationConfig {}

JPAConfiguration.java

@Configuration
@EnableJpaRepositories("com.test.dao")
@EnableTransactionManagement
public class JPAConfiguration {

@Bean
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factory.setPackagesToScan("com.test.model");
factory.setDataSource(restDataSource());
factory.setJpaPropertyMap(getPropertyMap());
factory.afterPropertiesSet();
return factory.getObject();
}

@Bean(destroyMethod = "close")
public DataSource restDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("test");
dataSource.setPassword("test");
return dataSource;
}

private Map<String, String> getPropertyMap() {
Map<String, String> hibernateProperties = new HashMap<>();
hibernateProperties.put("hibernate.hbm2ddl.auto", "update");
hibernateProperties.put("hibernate.show_sql", "true");
hibernateProperties.put("hibernate.format_sql", "true");
hibernateProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
return hibernateProperties;
}

@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory());
return txManager;
}

}

TestRepository.java

@Repository
public interface TestRepository extends JpaRepository<TestEntity, Long> {}

TestEntity.java

@Entity
@Table(name = "ent")
public class TestEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String descript;
//equals, hashcode, toString, getters, setters
}

AppInitializer.java

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
private WebApplicationContext rootContext;

@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{ApplicationConfig.class};
}

@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}

@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}

}

命令

jmap -histo <tomcat_pid>

在 tomcat 停止后仅显示项目结构中的 2 项:

com.test.config.dao.JPAConfiguration$$EnhancerBySpringCGLIB$$792cb231$$FastClassBySpringCGLIB$$45ff499c
com.test.config.dao.JPAConfiguration$$FastClassBySpringCGLIB$$10104c1e

有人有解决此问题的想法或建议吗?

最佳答案

这个小项目有2处内存泄漏:

  1. MySQL jdbc 驱动程序的问题。

我们必须添加 ContextLoaderListener 来注销 jdbc 驱动程序:

听众:

@WebListener
public class ContextListener extends ContextLoaderListener {

private final Logger log = LoggerFactory.getLogger(this.getClass());

@Override
public void contextInitialized(ServletContextEvent sce) {
log.info("-= Context started =-");

}

@Override
public void contextDestroyed(ServletContextEvent sce) {
super.contextDestroyed(sce);
log.info("-= Context destroyed =-");
try {
log.info("Calling MySQL AbandonedConnectionCleanupThread checkedShutdown");
com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.uncheckedShutdown();

} catch (Exception e) {
log.error("Error calling MySQL AbandonedConnectionCleanupThread checkedShutdown {}", e);
}

ClassLoader cl = Thread.currentThread().getContextClassLoader();

Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();

if (driver.getClass().getClassLoader() == cl) {

try {
log.info("Deregistering JDBC driver {}", driver);
DriverManager.deregisterDriver(driver);

} catch (SQLException ex) {
log.error("Error deregistering JDBC driver {}", driver, ex);
}

} else {
log.info("Not deregistering JDBC driver {} as it does not belong to this webapp's ClassLoader", driver);
}
}
}
}

或者如果您可以访问 tomcat 服务器,您可以在 tomcat/conf/server.xml 中修改监听器 example .

  1. 第二个问题是 jboss-logging 库中的已知内存泄漏 (link)。

在我们将这个库从 hibernate 依赖项中排除后,内存泄漏就消失了:

build.gradle:

group 'com.test'
version '1.0-SNAPSHOT'

apply plugin: 'java'
apply plugin: 'war'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile(group: 'org.hibernate', name: 'hibernate-entitymanager', version: '5.2.10.Final') {
exclude group: 'org.jboss.logging', module: 'jboss-logging'
}

compile group: 'org.springframework.data', name: 'spring-data-jpa', version: '1.11.4.RELEASE'

compile group: 'org.springframework', name: 'spring-webmvc', version: '4.3.9.RELEASE'

providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
providedCompile group: 'mysql', name: 'mysql-connector-java', version: '8.0.11'
compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
compile group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.25'
}

然后从 repo 构建 jar并添加到 tomcat /lib 文件夹。

jboss-logging 的问题可能已在 Java 9 ( pull request link ) 中修复。

关于mysql - 停止/重新部署时 Tomcat 7+ 内存泄漏。 Spring Data、JPA、Hibernate、MySQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45055122/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com