weixin_39929138
weixin_39929138
2020-11-21 23:52

在spring-mvc中通过线程调用方式使用weixin4j-server时,netty线程服务关闭异常

测试环境版本如下:


    <properties>
        <java-version>1.8</java-version>
        <springframework-version>4.3.8.RELEASE</springframework-version>
        <version-wechat4j>1.7.6</version-wechat4j>
        <version-wechat4j-server>1.1.8</version-wechat4j-server>
    </properties>

我按照你给的例子编写的自己的Thread实现


import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.handler.DebugMessageHandler;
import com.foxinmy.weixin4j.spring.SpringBeanFactory;
import com.foxinmy.weixin4j.startup.WeixinServerBootstrap;
import com.foxinmy.weixin4j.util.AesToken;
import io.netty.util.internal.logging.InternalLoggerFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 微信消息处理Netty服务配置
 * Created by hello on 2017/6/22.
 */

public class WechatServerThread implements ApplicationContextAware {

    private Logger logger = LogManager.getLogger(getClass());

    /**
     * 服务监听的端口号,目前微信只支持80端口,可以考虑用nginx做转发到此端口
     */
    private int port;
    /**
     * 服务器token信息
     * 明文模式:String aesToken = ""; 密文模式:AesToken aesToken = new
     * AesToken("公众号appid", "公众号token","公众号加密/解密消息的密钥");
     */
    private AesToken aesToken;

    /**
     * 处理微信消息的全限包名(也可通过addHandler方式一个一个添加)
     */
    private String handlerPackage="veda.oems.service.wechat.handler";

    /**
     * 用spring去获取bean
     */
    private ApplicationContext applicationContext;

    public WechatServerThread(){}


    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Environment environment = applicationContext.getEnvironment();
        this.applicationContext = applicationContext;
        // 设置
        String runModel = environment.getRequiredProperty("system.run.model");
        logger.info("wechat server in "+runModel+" environment");
        switch (runModel){
            case "develop":
                this.port = environment.getRequiredProperty("weixin4j.server.port", int.class);
                this.aesToken = new AesToken(
                        environment.getRequiredProperty("weixin4j.server.app.id", String.class),
                        environment.getRequiredProperty("weixin4j.server.app.token", String.class),
                        environment.getRequiredProperty("weixin4j.server.app.aeskey", String.class)
                );
                break;
            case "product":
                this.port = environment.getRequiredProperty("weixin4j.server.port", int.class);
                this.aesToken = new AesToken(
                        environment.getRequiredProperty("weixin4j.server.app.id", String.class),
                        environment.getRequiredProperty("weixin4j.server.app.token", String.class),
                        environment.getRequiredProperty("weixin4j.server.app.aeskey", String.class)
                );
            default:
                logger.info(" can not found the run model");
        }
        this.start();
    }

    private ExecutorService executor;

    /**
     * 启动函数
     */
    public void start() {
        executor = Executors.newCachedThreadPool();
        executor.execute(new Runnable() {

            public void run() {
                try {
                    logger.info("wechat message netty server start success");
                    new WeixinServerBootstrap(aesToken) // 指定开发者token信息。
                            .handlerPackagesToScan(handlerPackage) // 扫描处理消息的包。
                            .resolveBeanFactory(
                                    new SpringBeanFactory(applicationContext)) // 声明处理消息类由Spring容器去实例化。
                            .addHandler(DebugMessageHandler.global) // 当没有匹配到消息处理时输出调试信息,开发环境打开。
                            .openAlwaysResponse() // 当没有匹配到消息处理时输出空白回复(公众号不会出现「该公众号无法提供服务的提示」),正式环境打开。
                            .startup(port); // 绑定服务的端口号,即对外暴露(微信服务器URL地址)的服务端口。
                } catch (WeixinException e) {
                    InternalLoggerFactory.getInstance(getClass()).error( "wechat message netty server run error ", e);
                }
            }
        });
    }


    public void stop() {
        //executor.shutdownNow();
        executor.shutdown();
        logger.info("wechat message netty server stop success");
    }
}

我现在只是在测试,未正常投入生产使用(没有写任何的Handler),使用的那几个配置项都是我伪造的,测试时启动正常,但是我在IDEA里将Tomcat停止或重启的时候,虽然没有报任何的异常,但是会一直处在未关闭完成的状态,我将原本的 executor.shutdown(); 换成 executor.shutdownNow(); 后可以正常关闭,但是在关闭后会报一些异常,下面我将相关异常列出来:


"C:\Program Files\Apache Software Foundation\Tomcat 8.5\bin\catalina.bat" stop
Using CATALINA_BASE:   "C:\Users\xxx\.IntelliJIdea2017.1\system\tomcat\Unnamed_oems_2"
Using CATALINA_HOME:   "C:\Program Files\Apache Software Foundation\Tomcat 8.5"
Using CATALINA_TMPDIR: "C:\Program Files\Apache Software Foundation\Tomcat 8.5\temp"
Using JRE_HOME:        "C:\Program Files\Java\jdk1.8.0_121"
Using CLASSPATH:       "C:\Program Files\Apache Software Foundation\Tomcat 8.5\bin\bootstrap.jar;C:\Program Files\Apache Software Foundation\Tomcat 8.5\bin\tomcat-juli.jar"
22-Jun-2017 19:41:39.431 信息 [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
22-Jun-2017 19:41:39.432 信息 [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-8080"]
22-Jun-2017 19:41:39.512 信息 [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-8009"]
22-Jun-2017 19:41:39.585 信息 [main] org.apache.catalina.core.StandardService.stopInternal Stopping service Catalina
22-Jun-2017 19:41:39.592 信息 [localhost-startStop-2] org.springframework.context.support.AbstractApplicationContext.doClose Closing WebApplicationContext for namespace 'dispatcher-servlet': startup date [Thu Jun 22 19:41:11 CST 2017]; parent: Root WebApplicationContext
22-Jun-2017 19:41:39.593 信息 [localhost-startStop-2] org.springframework.context.support.AbstractApplicationContext.doClose Closing Root WebApplicationContext: startup date [Thu Jun 22 19:41:09 CST 2017]; root of context hierarchy
Exception in thread "pool-2-thread-1" [19:41:39:594] [INFO] - veda.oems.config.wechat.WechatServerThread.stop(WechatServerThread.java:112) - wechat message netty server stop success
java.lang.NoSuchMethodError: com.foxinmy.weixin4j.exception.WeixinException.<init>(Ljava/lang/String;Ljava/lang/Exception;)V
    at com.foxinmy.weixin4j.startup.WeixinServerBootstrap.startup(WeixinServerBootstrap.java:208)
    at com.foxinmy.weixin4j.startup.WeixinServerBootstrap.startup(WeixinServerBootstrap.java:170)
    at veda.oems.config.wechat.WechatServerThread$1.run(WechatServerThread.java:100)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
22-Jun-2017 19:41:39.617 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc The web application [oems] registered the JDBC driver [com.mysql.cj.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.
22-Jun-2017 19:41:39.626 信息 [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-8080"]
22-Jun-2017 19:41:39.627 信息 [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-8009"]
22-Jun-2017 19:41:39.627 信息 [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-8080"]
22-Jun-2017 19:41:39.628 信息 [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-8009"]
22-Jun-2017 19:41:41.698 信息 [nioEventLoopGroup-2-1] org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading Illegal access: this web application instance has been stopped already. Could not load [io.netty.util.concurrent.DefaultPromise$2]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
 java.lang.IllegalStateException: Illegal access: this web application instance has been stopped already. Could not load [io.netty.util.concurrent.DefaultPromise$2]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
    at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading(WebappClassLoaderBase.java:1305)
    at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForClassLoading(WebappClassLoaderBase.java:1293)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1158)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)

Exception in thread "nioEventLoopGroup-2-1" java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: Illegal access: this web application instance has been stopped already. Could not load [io.netty.util.concurrent.DefaultPromise$2]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
    at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForClassLoading(WebappClassLoaderBase.java:1295)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1158)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
    ... 5 more
Caused by: java.lang.IllegalStateException: Illegal access: this web application instance has been stopped already. Could not load [io.netty.util.concurrent.DefaultPromise$2]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
    at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading(WebappClassLoaderBase.java:1305)
    at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForClassLoading(WebappClassLoaderBase.java:1293)
    ... 7 more
Exception in thread "nioEventLoopGroup-2-2" java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
Exception in thread "nioEventLoopGroup-3-14" Exception in thread "nioEventLoopGroup-3-15" Exception in thread "nioEventLoopGroup-2-3" Exception in thread "nioEventLoopGroup-3-11" Exception in thread "nioEventLoopGroup-3-1" Exception in thread "nioEventLoopGroup-3-16" Exception in thread "nioEventLoopGroup-3-13" Exception in thread "nioEventLoopGroup-2-4" java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
Exception in thread "nioEventLoopGroup-3-12"    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
Exception in thread "nioEventLoopGroup-3-8" java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
Exception in thread "nioEventLoopGroup-3-9" Exception in thread "nioEventLoopGroup-3-7" Exception in thread "nioEventLoopGroup-3-3" Exception in thread "nioEventLoopGroup-3-5" Exception in thread "nioEventLoopGroup-3-4" Exception in thread "nioEventLoopGroup-3-10" Exception in thread "nioEventLoopGroup-3-6" Exception in thread "nioEventLoopGroup-3-2"    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589)
    at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)
Disconnected from server
</init>

在我使用 executor.shutdown(); 关闭,Tomcat处于未关闭完成的状态时对netty服务发了一次请求,也会出异常,我不知道netty关闭需要多久时间,我等了好一会也没见Tomcat完全停止,异常如下:


"C:\Program Files\Apache Software Foundation\Tomcat 8.5\bin\catalina.bat" stop
Using CATALINA_BASE:   "C:\Users\xxx\.IntelliJIdea2017.1\system\tomcat\Unnamed_oems_2"
Using CATALINA_HOME:   "C:\Program Files\Apache Software Foundation\Tomcat 8.5"
Using CATALINA_TMPDIR: "C:\Program Files\Apache Software Foundation\Tomcat 8.5\temp"
Using JRE_HOME:        "C:\Program Files\Java\jdk1.8.0_121"
Using CLASSPATH:       "C:\Program Files\Apache Software Foundation\Tomcat 8.5\bin\bootstrap.jar;C:\Program Files\Apache Software Foundation\Tomcat 8.5\bin\tomcat-juli.jar"
22-Jun-2017 19:54:50.257 信息 [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
22-Jun-2017 19:54:50.258 信息 [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-8080"]
22-Jun-2017 19:54:50.336 信息 [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-8009"]
22-Jun-2017 19:54:50.410 信息 [main] org.apache.catalina.core.StandardService.stopInternal Stopping service Catalina
22-Jun-2017 19:54:50.415 信息 [localhost-startStop-2] org.springframework.context.support.AbstractApplicationContext.doClose Closing WebApplicationContext for namespace 'dispatcher-servlet': startup date [Thu Jun 22 19:54:23 CST 2017]; parent: Root WebApplicationContext
22-Jun-2017 19:54:50.417 信息 [localhost-startStop-2] org.springframework.context.support.AbstractApplicationContext.doClose Closing Root WebApplicationContext: startup date [Thu Jun 22 19:54:21 CST 2017]; root of context hierarchy
[19:54:50:418] [INFO] - veda.oems.config.wechat.WechatServerThread.stop(WechatServerThread.java:112) - wechat message netty server stop success
22-Jun-2017 19:54:50.437 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc The web application [oems] registered the JDBC driver [com.mysql.cj.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.
22-Jun-2017 19:54:50.439 严重 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [oems] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal]) and a value of type [io.netty.util.internal.InternalThreadLocalMap] (value [io.netty.util.internal.InternalThreadLocalMap]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
22-Jun-2017 19:54:50.446 信息 [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-8080"]
22-Jun-2017 19:54:50.447 信息 [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-8009"]
22-Jun-2017 19:54:50.447 信息 [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-8080"]
22-Jun-2017 19:54:50.448 信息 [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-8009"]
22-Jun-2017 19:55:10.542 信息 [nioEventLoopGroup-2-1] org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading Illegal access: this web application instance has been stopped already. Could not load [io.netty.channel.socket.nio.NioSocketChannel]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
 java.lang.IllegalStateException: Illegal access: this web application instance has been stopped already. Could not load [io.netty.channel.socket.nio.NioSocketChannel]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
    at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading(WebappClassLoaderBase.java:1305)
    at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForClassLoading(WebappClassLoaderBase.java:1293)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1158)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
    at io.netty.channel.socket.nio.NioServerSocketChannel.doReadMessages(NioServerSocketChannel.java:139)
    at io.netty.channel.nio.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:68)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)

22-Jun-2017 19:55:10.543 信息 [nioEventLoopGroup-2-1] org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading Illegal access: this web application instance has been stopped already. Could not load [java.nio.channels.SocketChannel]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
 java.lang.IllegalStateException: Illegal access: this web application instance has been stopped already. Could not load [java.nio.channels.SocketChannel]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
    at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading(WebappClassLoaderBase.java:1305)
    at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForClassLoading(WebappClassLoaderBase.java:1293)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1158)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
    at io.netty.channel.socket.nio.NioServerSocketChannel.doReadMessages(NioServerSocketChannel.java:146)
    at io.netty.channel.nio.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:68)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)

目前我打算先直接try catch掉,找了许久的wechat的Java的SDK,就你这更新的比较勤,打算用下试试,加油哦

该提问来源于开源项目:foxinmy/weixin4j

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

6条回答

  • weixin_39986171 weixin_39986171 5月前

    感谢关注。

    我这边也重现,暂时没有头绪,不过在WeixinServerBootstrap类新增了shutdown方法

    我再调试一下吧。:)

    点赞 评论 复制链接分享
  • weixin_39929138 weixin_39929138 5月前

    嗯嗯

    点赞 评论 复制链接分享
  • weixin_39875629 weixin_39875629 5月前

    目前做的一个类似项目因存在写异步日志的线程一直存活,使用tomcat的关闭命令stop.sh是关闭不了tomcat的,只能使用kill强杀,看上去你这个是由于线程池中的线程还在运行,你使用executor.shutdownNow()强杀所有线程,netty服务监听到无服务导致抛出的异常吧。

    点赞 评论 复制链接分享
  • weixin_39986171 weixin_39986171 5月前

    你好,应该是你说得这样,但是我在服务启动类WeixinServerBootstrap中加了netty的shutdown方法,然后在自己的线程中的stop方法中调用也会抛出上述java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2异常,netty启动的线程可以正常停止。

    java
    public boolean shutdown() {
            if (bootstrap == null) {
                return false;
            }
            ServerBootstrapConfig c = bootstrap.config();
            c.group().shutdownGracefully();
            c.childGroup().shutdownGracefully();
            messageHandlerList = null;
            messageInterceptorList = null;
            messageDispatcher = null;
            bootstrap = null;
            return true;
        }
    

    初步怀疑是tomcat的ClassLoader的原因,但不知道从何处着手。

    点赞 评论 复制链接分享
  • weixin_39986171 weixin_39986171 5月前

    似乎解决了。

    首先需要在web.xml配置一个listener

    xml
        <listener>
            <listener-class>com.foxinmy.weixin4j.example.server.Weixin4jServerStartupListener</listener-class>
        </listener>
    

    listener实现ServletContextListener接口:

    java
    public class Weixin4jServerStartupListener implements ServletContextListener {
        /**
         * 服务监听的端口号,目前微信只支持80端口,可以考虑用nginx做转发到此端口
         */
        private final int port;
        /**
         * 服务器token信息
         */
        /**
         * 明文模式:String aesToken = ""; 密文模式:AesToken aesToken = new
         * AesToken("公众号appid", "公众号token","公众号加密/解密消息的密钥");
         */
        private final AesToken aesToken;
        /**
         * 处理微信消息的全限包名(也可通过addHandler方式一个一个添加)
         */
        private final String handlerPackage;
    
        public Weixin4jServerStartupListener() {
            // 可以考虑通过参数获取
            this.port = 30000;
            this.aesToken = new AesToken("weixin4j");
            this.handlerPackage = "com.foxinmy.weixin4j.example.server.handler";
        }
    
        private WeixinServerBootstrap bootstrap;
    
        /**
         * 启动服务
         *
         *  applicationContext
         */
        public void start(final ApplicationContext applicationContext) {
            new Thread(new Runnable() {
    
                public void run() {
                    bootstrap = new WeixinServerBootstrap(aesToken) // 指定开发者token信息。
                            .handlerPackagesToScan(handlerPackage) // 扫描处理消息的包。
                            .resolveBeanFactory(new SpringBeanFactory(applicationContext)) // 声明处理消息类由Spring容器去实例化。
                            .addHandler(DebugMessageHandler.global) // 当没有匹配到消息处理时输出调试信息,开发环境打开。
                            .openAlwaysResponse(); // 当没有匹配到消息处理时输出空白回复(公众号不会出现「该公众号无法提供服务的提示」),正式环境打开。
                    bootstrap.startup(port); // 绑定服务的端口号,即对外暴露(微信服务器URL地址)的服务端口。
                }
            }).start();
        }
    
        /**
         * 关闭服务
         */
        public void stop() {
            bootstrap.shutdown(true);
        }
    
    
        public void contextInitialized(ServletContextEvent sce) {
            start(WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext()));
        }
    
    
        public void contextDestroyed(ServletContextEvent sce) {
            stop();
        }
    }
    

    WeixinServerBootstrap关闭服务shutdown方法如下:

    java
     /**
         * 关闭微信服务
         *
         *  blocking
         *            阻塞关闭
         * 
         */
        public boolean shutdown(boolean blocking) {
            if (bootstrap == null) {
                return false;
            }
            ServerBootstrapConfig c = bootstrap.config();
            Future> bossF = c.group().shutdownGracefully();
            Future> workerF = c.childGroup().shutdownGracefully();
            if (blocking) {
                bossF.awaitUninterruptibly();
                workerF.awaitUninterruptibly();
            }
            messageHandlerList = null;
            messageInterceptorList = null;
            messageDispatcher = null;
            bootstrap = null;
            return true;
        }
    

    我看看能不能在weixin4j-server包里写一个通用的listener

    感谢反馈。

    点赞 评论 复制链接分享
  • weixin_39929138 weixin_39929138 5月前

    嗯,有空我再测试下

    点赞 评论 复制链接分享

相关推荐