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
相关产品推荐
相关产品推荐

