@Configuration
public class DataSourceConfiguration
{
@Autowired
private Environment env;
@Bean(destroyMethod = "close")
public ComboPooledDataSource dataSource()
{
String datasourcePathStartsWith = "datasource.";
ComboPooledDataSource dataSource = new ComboPooledDataSource();
try
{
dataSource.setContextClassLoaderSource("library");
dataSource.setPrivilegeSpawnedThreads(true);
dataSource.setDriverClass("oracle.jdbc.driver.OracleDriver");
dataSource.setJdbcUrl(env.getProperty(datasourcePathStartsWith + "url"));
dataSource.setUser(env.getProperty(datasourcePathStartsWith + "user"));
dataSource.setPassword(env.getProperty(datasourcePathStartsWith + "password"));
dataSource.setMinPoolSize(Integer.parseInt(env.getProperty(datasourcePathStartsWith + "minPoolSize")));
dataSource.setMaxPoolSize(Integer.parseInt(env.getProperty(datasourcePathStartsWith + "maxPoolSize")));
dataSource.setCheckoutTimeout(Integer.parseInt(env.getProperty(datasourcePathStartsWith + "checkoutTimeout")));
dataSource.setMaxIdleTime(Integer.parseInt(env.getProperty(datasourcePathStartsWith + "maxIdleTime")));
dataSource.setMaxStatements(Integer.parseInt(env.getProperty(datasourcePathStartsWith + "maxStatements")));
}
catch (PropertyVetoException e)
{
e.printStackTrace();
}
return dataSource;
}
}
Voici mon code. Cela fonctionne "bien" sur Tomcat 7 - quand je redéploie plusieurs fois l'application et que j'utilise la fonction "Trouver des fuites", cela ne montre rien. Mais si j'ajoute sessionFactory, les problèmes apparaissent tous les redéployer:Problème de Permgen lors de l'utilisation de LocalSessionFactoryBean de Spring
Les applications Web suivantes ont été arrêtées (rechargées, non déployé), mais leurs classes de courses précédentes sont toujours chargées en mémoire, ce qui provoque une fuite de mémoire (utilisez un profileur pour confirmer): /testPermGen
/testPermGen
/testPermGen
@Bean
public LocalSessionFactoryBean sessionFactory(DataSource dataSource)
{
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
return sessionFactoryBean;
}
J'ai essayé ce code, sans câblage à dataSource, sans succès. On dirait que le problème est avec LocalSessionFactoryBean non fermé à l'arrêt de l'application.
@Bean(destroyMethod = "destroy")
public LocalSessionFactoryBean sessionFactory()
{
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
return sessionFactoryBean;
}
Tomcat est en cours d'exécution avec des drapeaux suivants:
-XX:MaxPermSize=128m
-XX:+UseConcMarkSweepGC
-XX:+CMSClassUnloadingEnabled
-XX:+CMSPermGenSweepingEnabled
Il est possible de résoudre ce problème avec les fuites de mémoire?
MISE À JOUR:
J'ai téléchargé l'ensemble du projet (4 fichiers) sur GitHub pour reproduire la fuite de mémoire: https://github.com/anton-09/TestPermGen
classloader fuite de prévention deMattias Jiderhamn n'a pas aidé beaucoup, je avez obtenu ce journal dans Tomcat 7:
июл 03, 2017 11:44:27 AM se.jiderhamn.classloader.leak.prevention.JULLogger warn
WARNING: Waiting for Thread 'Thread[Resource Destroyer in BasicResourcePool.close(),5,main]' of type com.mchange.v2.resourcepool.BasicResourcePool$5 loaded by protected ClassLoader with contextClassLoader = protected ClassLoader or child for 5000 ms. Thread stack trace:
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at oracle.net.ns.Packet.receive(Packet.java:300)
at oracle.net.ns.DataPacket.receive(DataPacket.java:106)
at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:315)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:260)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:185)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:102)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:124)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:80)
at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1137)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:290)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
at oracle.jdbc.driver.T4C7Ocommoncall.doOLOGOFF(T4C7Ocommoncall.java:61)
at oracle.jdbc.driver.T4CConnection.logoff(T4CConnection.java:543)
at oracle.jdbc.driver.PhysicalConnection.close(PhysicalConnection.java:3984)
at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:642)
at com.mchange.v2.c3p0.impl.NewPooledConnection.closeMaybeCheckedOut(NewPooledConnection.java:255)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.destroyResource(C3P0PooledConnectionPool.java:622)
at com.mchange.v2.resourcepool.BasicResourcePool$1DestroyResourceTask.run(BasicResourcePool.java:1076)
at com.mchange.v2.resourcepool.BasicResourcePool.destroyResource(BasicResourcePool.java:1101)
at com.mchange.v2.resourcepool.BasicResourcePool.destroyResource(BasicResourcePool.java:1062)
at com.mchange.v2.resourcepool.BasicResourcePool.access$100(BasicResourcePool.java:44)
at com.mchange.v2.resourcepool.BasicResourcePool$5.run(BasicResourcePool.java:1316)
июл 03, 2017 11:44:27 AM se.jiderhamn.classloader.leak.prevention.JULLogger info
INFO: Thread 'Thread[Resource Destroyer in BasicResourcePool.close(),5,main]' of type com.mchange.v2.resourcepool.BasicResourcePool$5 loaded by protected ClassLoader with contextClassLoader = protected ClassLoader or child no longer alive - no action needed.
On dirait everithing ok, mais « trouver les fuites » Tomcat de reportages sur les nouvelles fuites de mémoire.
SOLUTION
Le problème est avec la journalisation JBoss inclus dans la dépendance Hibernate. J'ai exclu la dépendance jboss-logging de hibernate-core, copié jboss-logging-3.3.0.Final.jar dans le dossier "lib" de Tomcat et le problème est parti.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
<exclusions>
<exclusion>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging-annotations</artifactId>
</exclusion>
</exclusions>
</dependency>
Essayez une autre connexion mise en œuvre de la piscine? Spring Boot par exemple prend en charge (dans l'ordre de préférence): Tomcat, HikariCP, DBCP (obsolète), DBCP2 – Strelok