在spring-mvc中通过线程调用方式使用weixin4j-server时,netty线程服务关闭异常
HelloSetsuna opened this issue · 6 comments
测试环境版本如下:
<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.
*/
@Component
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(){}
@Override
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() {
@Override
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);
}
}
});
}
@PreDestroy
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
在我使用 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@5eecc734]) and a value of type [io.netty.util.internal.InternalThreadLocalMap] (value [io.netty.util.internal.InternalThreadLocalMap@3c48085b]) 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,就你这更新的比较勤,打算用下试试,加油哦
感谢关注。
我这边也重现,暂时没有头绪,不过在WeixinServerBootstrap
类新增了shutdown
方法
我再调试一下吧。:)
嗯嗯
目前做的一个类似项目因存在写异步日志的线程一直存活,使用tomcat的关闭命令stop.sh是关闭不了tomcat的,只能使用kill强杀,看上去你这个是由于线程池中的线程还在运行,你使用executor.shutdownNow()强杀所有线程,netty服务监听到无服务导致抛出的异常吧。
@michjony 你好,应该是你说得这样,但是我在服务启动类WeixinServerBootstrap
中加了netty的shutdown
方法,然后在自己的线程中的stop
方法中调用也会抛出上述java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2
异常,netty启动的线程可以正常停止。
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的原因,但不知道从何处着手。
似乎解决了。
首先需要在web.xml
配置一个listener
<listener>
<listener-class>com.foxinmy.weixin4j.example.server.Weixin4jServerStartupListener</listener-class>
</listener>
listener实现ServletContextListener
接口:
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;
/**
* 启动服务
*
* @param applicationContext
*/
public void start(final ApplicationContext applicationContext) {
new Thread(new Runnable() {
@Override
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);
}
@Override
public void contextInitialized(ServletContextEvent sce) {
start(WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext()));
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
stop();
}
}
WeixinServerBootstrap
关闭服务shutdown
方法如下:
/**
* 关闭微信服务
*
* @param blocking
* 阻塞关闭
* @return
*/
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
感谢反馈。
嗯,有空我再测试下