web-dev-qa-db-fra.com

L'application Web [] a enregistré le pilote JDBC [com.mysql.jdbc.Driver] mais n'a pas réussi à le désinscrire lorsque l'application Web a été arrêtée

J'ai vu quelques problèmes similaires sur stackoverflow mais je n'ai pas pu trouver comment résoudre mon problème. Après avoir ajouté Spring Security à mon projet Spring MVC, j'ai eu l'exception suivante:

Jul 20, 2014 3:18:04 PM org.Apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

Voici mon mysql-connecteur dans le pom.xml

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-Java</artifactId>
      <version>5.1.31</version>
    </dependency>

Voici les classes que j'ai ajoutées:

@Component
@Transactional
public class UserDetailsServiceImpl implements UserDetailsService{

@Autowired
private UserDAO userDAO;

@Autowired
private UserAssembler userAssembler;

private static final Logger logger = LoggerFactory.getLogger(UserDetailsServiceImpl.class);

@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
    User user = userDAO.findByEmail(username);

    if(null == user) throw new UsernameNotFoundException("User not found");

    return userAssembler.buildUserFromUser(user);
}
}

et assembleur

 @Service("assembler")

public class UserAssembler {

@Autowired
private UserDAO userDAO;

@Transactional(readOnly = true)
public User buildUserFromUser(net.viralpatel.contact.model.User user) {
    String role = "ROLE_USER";//userEntityDAO.getRoleFromUserEntity(userEntity);

    Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    authorities.add(new GrantedAuthorityImpl(role));

    return new User(user.getLogin(), user.getPassword(), true, true, true, true,  authorities);
}
}

Voici mon spring-security.xml

<beans:bean id="webexpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" />

<http auto-config="true">
    <intercept-url pattern="/account/*" access="ROLE_ADMIN" />
    <form-login login-page="/login" default-target-url="/account/overview" authentication-failure-url="/login?error=true"/>
    <remember-me/>
</http>

<beans:bean id="myUserDetailsService" class="net.viralpatel.contact.service.UserDetailsServiceImpl" />


<authentication-manager alias="authenticationManager">
    <authentication-provider user-service-ref="myUserDetailsService" />
</authentication-manager>

MODIFIÉ:

INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the Java.library.path: /opt/idea-IU-135.909/bin::/usr/Java/packages/lib/AMD64:/usr/lib64:/lib64:/lib:/usr/lib
Jul 20, 2014 3:58:36 PM org.Apache.catalina.core.JreMemoryLeakPreventionListener lifecycleEvent
SEVERE: Failed to load class com.mysql.jdbc.NonRegisteringDriver during Tomcat start to prevent possible memory leaks.
Java.lang.ClassNotFoundException: com.mysql.jdbc.NonRegisteringDriver
12
user3127896

ce que j'ai fait était juste de mettre le mysql-connector-Java-5.1.31-bin.jar dans $ CATALINA_HOME/lib. aucune modification à server.xml.

4

Votre application n'a pas de défaut. C'est la conception de JDBC. Le pilote JDBC est chargé et enregistré par la webapp lors de la première création d'une connexion à la base de données.

Cela signifie que le pilote est chargé avec le chargeur de classe d'application Web. Lors du retrait du déploiement, le pilote n'est pas annulé, ce qui empêche à son tour vos classes Webapp de GC. Cela crée effectivement une fuite de mémoire.

Pour éviter cette fuite de mémoire particulière, vous devez modifier votre Tomcat/conf/server.xml et changer

<Listener className="org.Apache.catalina.core.JreMemoryLeakPreventionListener" />

à

<Listener 
className="org.Apache.catalina.core.JreMemoryLeakPreventionListener"
classesToInitialize="com.mysql.jdbc.NonRegisteringDriver" />

Excluez le pilote JDBC de votre artefact webapp et placez-le dans le Tomcat/lib répertoire. Désormais, le pilote JDBC est chargé par Tomcat au démarrage et n'est lié à aucun chargeur de classe webapps.

Pourquoi devrais-je modifier le server.xml?

Une autre fuite de mémoire se manifeste en raison du "thread de nettoyage de connexion abandonné" de MySQL. Ce thread commence par la première demande et contient une référence au chargeur de classe de la webapp. Avec classesToInitialize, vous pouvez également éviter cette fuite de mémoire.

17
Kamill Sokol