You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot集成JJWT停止应用时出现内存泄漏警告求助

SpringBoot 2.7.8 + JJWT 0.11.2 应用停止时Hikari线程未关闭引发内存泄漏警告

我之前使用旧版本JJWT与SpringBoot配合运行正常,但切换到SpringBoot 2.7.8和JJWT 0.11.2版本后,停止应用时总会出现以下警告:

2023-03-22 10:57:39.430  INFO 7316 --- [on(7)-127.0.0.1] inMXBeanRegistrar$SpringApplicationAdmin : Application shutdown requested.
2023-03-22 10:57:39.441  INFO 7316 --- [on(7)-127.0.0.1] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2023-03-22 10:57:39.446  WARN 7316 --- [on(7)-127.0.0.1] o.a.c.loader.WebappClassLoaderBase       : The web application [ROOT] appears to have started a thread named [HikariPool-1 housekeeper] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.base@17.0.5/jdk.internal.misc.Unsafe.park(Native Method)
java.base@17.0.5/java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:252)
java.base@17.0.5/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:1672)
java.base@17.0.5/java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1182)
java.base@17.0.5/java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:899)
java.base@17.0.5/java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1062)
java.base@17.0.5/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1122)
java.base@17.0.5/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
java.base@17.0.5/java.lang.Thread.run(Thread.java:833)
2023-03-22 10:57:39.447  WARN 7316 --- [on(7)-127.0.0.1] o.a.c.

提示Web应用启动的HikariPool-1 housekeeper线程未停止,极可能造成内存泄漏。同时停止应用时会生成HeapDump。

依赖配置

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.8</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>

<groupId>com.cubo333</groupId>
<artifactId>auth</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>auth</name>
<description>Serviço auth</description>
<properties>
    <java.version>11</java.version>
</properties>

JJWT相关依赖:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.2</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.2</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.2</version>
</dependency>

Repository代码

public interface UsersRepository extends JpaRepository<Users, UUID>, JpaSpecificationExecutor<Users> {

    boolean existsByUsername(String username);

    boolean existsByEmail(String email);

    @EntityGraph(attributePaths = "roles", type = EntityGraph.EntityGraphType.FETCH)
    Optional<Users> findByUsername(String username);

    @EntityGraph(attributePaths = "roles", type = EntityGraph.EntityGraphType.FETCH)
    Optional<Users> findById(UUID userID);
}

UserDetails服务代码

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UsersRepository usersRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Users userModel = usersRepository.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username));
        return new UserDetailIsmpl(userModel);
    }

    public UserDetails loadUserByUserId(UUID userId) throws AuthenticationCredentialsNotFoundException {
        Users userModel = usersRepository.findById(userId).orElseThrow(() -> new UsernameNotFoundException("User Not Found with userId: " + userId));
        return new UserDetailIsmpl(userModel);
    }
}

认证令牌过滤器代码

@Log4j2
public class AuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    JwtProvider jwtProvider;
    @Autowired
    UserDetailsServiceImpl userDetailsServiceImpl;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            String jwtStr = getTokenHeader(request);
            if (jwtStr != null && this.jwtProvider.validateJwt(jwtStr)) {
                String userId = this.jwtProvider.getSubjectJwt(jwtStr);
                UserDetails userDetails = this.userDetailsServiceImpl.loadUserByUserId(UUID.fromString(userId));
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));  
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        } catch (Exception e) {
            log.error("Cannot set user Authentication", e);
        }
        filterChain.doFilter(request, response);
    }

    private String getTokenHeader(HttpServletRequest request) {
        String headerAuth = request.getHeader("Authorization");
        if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
            return headerAuth.substring(7, headerAuth.length());
        }
        return null;
    }

}

应用配置

server:
  port: 5000

spring:
  application:
    name: auth-user
  datasource:
    url: jdbc:mysql://localhost:3306/authentication_service_db
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 
  jpa:
    hibernate:
      ddl-auto: update
      dialect: org.hibernate.dialect.MySQL8Dialect
      jdbc:
        lob.non-contextual-creation: true
    properties: 
      hibernate:
        show_sql: true 

请求协助解决该内存泄漏问题。

内容的提问来源于stack exchange,提问作者Tiago Antunes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 07:16:59