【问题标题】:How to solve the problem that many thread blocked in org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader#loadClass如何解决org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader#loadClass中多线程阻塞的问题
【发布时间】:2020-08-14 13:15:41
【问题描述】:

我发现大多数线程在 org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader#loadClass 中被阻塞,当在 spring boot 项目中的 api 基础上运行压力测试时。项目的信息如下:

Web服务器:嵌入tomcat 9.0.31;

框架:spring boot 2.1.4.RELEASE;

缓存:hazelcast 3.11.2;

以下是在 yml 文件中嵌入 tomcat 配置:

server:
  port: 8081
  tomcat:
    max-threads: 300
    min-spare-threads: 50

只有 31 个线程状态为 RUNNABLE,但 287 个线程状态为 BLOCKED。BLOCKED 线程都阻塞在同一个锁中,只有一个线程获得锁。

java代码是:

@CacheConfig(cacheNames = CacheConstants.CACHE_CHANNEL_TVCOLUMN)
@Slf4j
@Service
public class ChannelTvColumnServiceImpl implements ChannelTvColumnService {

    @Autowired
    private ChannelTvColumnMapper channelTvColumnMapper;

    @Override
    @Cacheable(key = "T(String).valueOf(#channelPk)")
    public long findTvColumnPkByChanelPk(long channelPk) {
        ChannelTvColumnEntity entity = channelTvColumnMapper.findByChanelPk(channelPk);
        if (entity != null) {
            return entity.getTvColumnPk();
        }
        return 0;
    }

    @CacheEvict(allEntries = true)
    @Override
    public void removeChannelTvColumnMappingCache() {
    }
}

287个BLOCK线程都在等待同一个锁,栈strace是:

"http-nio-8081-exec-352" #496 daemon prio=5 os_prio=0 tid=0x00007ff51c237000 nid=0x5c6f waiting for monitor entry [0x00007ff4e9c42000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader.loadClass(TomcatEmbeddedWebappClassLoader.java:66)
        - waiting to lock <0x000000070312c2b0> (a java.lang.Object)
        at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1188)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:348)
        at org.springframework.util.ClassUtils.forName(ClassUtils.java:275)
        at org.springframework.expression.spel.support.StandardTypeLocator.findType(StandardTypeLocator.java:103)
        at org.springframework.expression.spel.ExpressionState.findType(ExpressionState.java:155)
        at org.springframework.expression.spel.ast.TypeReference.getValueInternal(TypeReference.java:69)
        at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:53)
        at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:89)
        at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:109)
        at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:265)
        at org.springframework.cache.interceptor.CacheOperationExpressionEvaluator.key(CacheOperationExpressionEvaluator.java:104)
        at org.springframework.cache.interceptor.CacheAspectSupport$CacheOperationContext.generateKey(CacheAspectSupport.java:778)
        at org.springframework.cache.interceptor.CacheAspectSupport.generateKey(CacheAspectSupport.java:575)
        at org.springframework.cache.interceptor.CacheAspectSupport.findCachedItem(CacheAspectSupport.java:518)
        at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:401)
        at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:345)
        at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
        at cn.xxx.xxx.channel.service.impl.ChannelTvColumnServiceImpl$$EnhancerBySpringCGLIB$$ed4e124b.findTvColumnPkByChanelPk(<generated>)
        at cn.xxx.xxx.news.controller.v1.ChannelNewsController.getChannelNews(ChannelNewsController.java:69)
        at sun.reflect.GeneratedMethodAccessor231.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at cn.xxx.xxx.apiauth.filter.ApiAuthFilter.doFilter(ApiAuthFilter.java:124)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:688)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1639)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
        - locked <0x00000006fac89ee8> (a org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
        - <0x00000007053bd608> (a java.util.concurrent.ThreadPoolExecutor$Worker)

拥有锁的线程堆栈跟踪是:

"http-nio-8081-exec-47" #160 daemon prio=5 os_prio=0 tid=0x00007ff5a56f8000 nid=0x53cd runnable [0x00007ff4fcf48000]
   java.lang.Thread.State: RUNNABLE
        at java.lang.Throwable.fillInStackTrace(Native Method)
        at java.lang.Throwable.fillInStackTrace(Throwable.java:783)
        - locked <0x00000006c6945770> (a java.lang.ClassNotFoundException)
        at java.lang.Throwable.<init>(Throwable.java:287)
        at java.lang.Exception.<init>(Exception.java:84)
        at java.lang.ReflectiveOperationException.<init>(ReflectiveOperationException.java:75)
        at java.lang.ClassNotFoundException.<init>(ClassNotFoundException.java:82)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        - locked <0x000000070370a870> (a java.lang.Object)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:411)
        - locked <0x000000070312cfb8> (a java.lang.Object)
        at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:93)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:348)
        at org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader.loadFromParent(TomcatEmbeddedWebappClassLoader.java:112)
        at org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader.doLoadClass(TomcatEmbeddedWebappClassLoader.java:85)
        at org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader.loadClass(TomcatEmbeddedWebappClassLoader.java:68)
        - locked <0x000000070312c2b0> (a java.lang.Object)
        at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1188)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:348)
        at org.springframework.util.ClassUtils.forName(ClassUtils.java:275)
        at org.springframework.expression.spel.support.StandardTypeLocator.findType(StandardTypeLocator.java:103)
        at org.springframework.expression.spel.ExpressionState.findType(ExpressionState.java:155)
        at org.springframework.expression.spel.ast.TypeReference.getValueInternal(TypeReference.java:69)
        at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:53)
        at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:89)
        at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:109)
        at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:265)
        at org.springframework.cache.interceptor.CacheOperationExpressionEvaluator.key(CacheOperationExpressionEvaluator.java:104)
        at org.springframework.cache.interceptor.CacheAspectSupport$CacheOperationContext.generateKey(CacheAspectSupport.java:778)
        at org.springframework.cache.interceptor.CacheAspectSupport.generateKey(CacheAspectSupport.java:575)
        at org.springframework.cache.interceptor.CacheAspectSupport.findCachedItem(CacheAspectSupport.java:518)
        at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:401)
        at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:345)
        at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
        at cn.xxx.xxx.channel.service.impl.ChannelTvColumnServiceImpl$$EnhancerBySpringCGLIB$$ed4e124b.findTvColumnPkByChanelPk(<generated>)
        at cn.xxx.xxx.news.controller.v1.ChannelNewsController.getChannelNews(ChannelNewsController.java:69)
        at sun.reflect.GeneratedMethodAccessor231.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at cn.xxx.xxx.apiauth.filter.ApiAuthFilter.doFilter(ApiAuthFilter.java:124)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:688)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1639)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
        - locked <0x00000006fac0ac98> (a org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
        - <0x0000000703181010> (a java.util.concurrent.ThreadPoolExecutor$Worker)

jvm线程分析如下图: analyze of the jvm thread stack

根据线程栈,我发现函数org.springframework.expression.spel.ast.TypeReference#getValueInternal会被调用,函数源代码如下:

    @Override
    public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
        // TODO possible optimization here if we cache the discovered type reference, but can we do that?
        String typeName = (String) this.children[0].getValueInternal(state).getValue();
        Assert.state(typeName != null, "No type name");
        if (!typeName.contains(".") && Character.isLowerCase(typeName.charAt(0))) {
            TypeCode tc = TypeCode.valueOf(typeName.toUpperCase());
            if (tc != TypeCode.OBJECT) {
                // It is a primitive type
                Class<?> clazz = makeArrayIfNecessary(tc.getType());
                this.exitTypeDescriptor = "Ljava/lang/Class";
                this.type = clazz;
                return new TypedValue(clazz);
            }
        }
        Class<?> clazz = state.findType(typeName);
        clazz = makeArrayIfNecessary(clazz);
        this.exitTypeDescriptor = "Ljava/lang/Class";
        this.type = clazz;
        return new TypedValue(clazz);
    }

我在函数中找到了一个todo cmets(TODO possible optimization here if we cache the discovered type),所以没有缓存类型。由于没有缓存类型,所以每次调用函数时都会执行代码Class&lt;?&gt; clazz = state.findType(typeName)

最后会调用函数org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader#loadClass,函数中有一个synchronized的代码块,所以很多线程必须阻塞在那里等待获取对象的监控锁。函数org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader#loadClass的代码源是:

    @Override
    public Class<?> loadClass(String name, boolean resolve)
            throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            Class<?> result = findExistingLoadedClass(name);
            result = (result != null) ? result : doLoadClass(name);
            if (result == null) {
                throw new ClassNotFoundException(name);
            }
            return resolveIfNecessary(result, resolve);
        }
    }

以下是我的 hazelcast 配置和用法:

1.导入项目pom文件中的jar包:

        <dependency>
            <groupId>com.hazelcast</groupId>
            <artifactId>hazelcast</artifactId>
        </dependency>
        <dependency>
            <groupId>com.hazelcast</groupId>
            <artifactId>hazelcast-spring</artifactId>
        </dependency>

2.配置hazelcast:

@Configuration
public class HazelcastConfiguration {

    @Value("${spring.profiles.active:Unknown}")
    private String activeProfile;
    @Value("${spring.application.name:Unknown}")
    private String applicationName;
    @Value("${hazelcast.syncIp}")
    private String syncIp;
    @Value("${hazelcast.manCenterIp:}")
    private String mngCenterIp;

    public HazelcastConfiguration() {
    }

    @Bean
    public Config hazelCastConfig() {
        Config config = new Config();
        config.getGroupConfig().setName(applicationName + "-" + activeProfile);
        if (StringUtils.hasText(mngCenterIp)) {
            config.getManagementCenterConfig().setEnabled(true);
            config.getManagementCenterConfig().setUrl(String.format("http://%s/hazelcast-mancenter", mngCenterIp));
        }
        JoinConfig join = config.getNetworkConfig().getJoin();
        join.getMulticastConfig()
                .setEnabled(false);
        join.getTcpIpConfig()
                .addMember(syncIp)
                .setEnabled(true);
        config.setInstanceName("hazelcast-instance")
                .addReplicatedMapConfig(
                        new ReplicatedMapConfig()
                                .setName(CacheConstants.CACHE_ALL_API_KEY_AND_SECRET)
                                .setQuorumName(CacheConstants.QUORUM_NAME)
                );
        return config;
    }
}

4.使用hazelcast通过spring cache注解@Cacheable来缓存数据,像这样:

    @Override
    @Cacheable(key = "T(String).valueOf(#channelPk)")
    public long findTvColumnPkByChanelPk(long channelPk) {
        ChannelTvColumnEntity entity = channelTvColumnMapper.findByChanelPk(channelPk);
        if (entity != null) {
            return entity.getTvColumnPk();
        }
        return 0;
    }

【问题讨论】:

  • 这似乎与您正在使用的 hazelcast 缓存有关 - 您能否添加更多关于您如何配置缓存以及如何使用它的信息?
  • @somshivam 谢谢,我已经更新了问题描述并添加了 hazelcast 配置和使用信息。

标签: java spring-boot tomcat hazelcast spring-cache


【解决方案1】:

根据release notes at Hazelcast,有几个与死锁有关的问题已修复。
您很幸运能够重现该问题 - 所以请升级到您可以升级到的最新版本(3.12.7 是他们在 3.x 系列中的最后一个版本)。
希望问题得到解决 - 如果没有,请获取 Hazelcast 配置的所有详细信息,并在他们的 GitHub 处打开问题

【讨论】:

  • 我尝试将 hazelcast 版本从 3.11.2 更新到 3.12.7,但问题仍然存在。让我困惑的是线程堆栈跟踪没有 hazelcast 信息。
猜你喜欢
  • 1970-01-01
  • 2016-06-11
  • 1970-01-01
  • 2021-08-05
  • 1970-01-01
  • 2021-01-02
  • 1970-01-01
  • 1970-01-01
  • 2015-05-01
相关资源
最近更新 更多