Tomcat8.0.36:WebappClassLoaderBase 难以捉摸的 nullpointerexception

Tomcat 8.0.36: WebappClassLoaderBase elusive nullpointerexception

问题:

问题是我在 Tomcat 中得到 NullPointerException in WebappClassLoaderBase,但没有太多解释为什么会这样。据我所知,它从 8.0.35 版开始发生......

异常跟踪:

java.lang.NullPointerException
    org.apache.catalina.loader.WebappClassLoaderBase.binaryNameToPath(WebappClassLoaderBase.java:2562)
    org.apache.catalina.loader.WebappClassLoaderBase.findLoadedClass0(WebappClassLoaderBase.java:2730)
    org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1208)
    org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1166)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528)
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1099)
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:670)
    org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2508)
    org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2497)
    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.lang.Thread.run(Thread.java:745)

产生问题的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

<servlet>
    <servlet-name>FirstServlet</servlet-name>
    <async-supported>true</async-supported>
</servlet>

<servlet>
    <servlet-name>SecondServlet</servlet-name>
    <enabled>false</enabled>
</servlet>

<session-config>
    <session-timeout>7</session-timeout>
    <cookie-config>
        <http-only>true</http-only>
        <secure>true</secure>
    </cookie-config>
</session-config>

<security-constraint>
    <display-name>HTTPS</display-name>
    <web-resource-collection>
        <web-resource-name>HTTPS Constraint</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>
<!-- IMPORTED web.xml MODULES END -->

</web-app>

我通过在 web.xml 文件中添加 <servlet-class> 标签解决了这个问题。

AFAICT 我不需要这样做,因为在我的代码中我有 @WebServlet 注释应该已经用 Tomcat.

注册了 class 名称

我在 Debian Wheezy Linux、Java 8、Jersey 2.24、Tomcat 8.0.38 上开发时看到了这个问题,并尝试部署 war 文件我的开发人员文件中的 Tomcat 8.0 默认使用操作系统中的 Java 7。我安装了多个版本的 Java 用于开发。为了解决这个问题,我创建了一个简短的脚本来导出 JAVA_HOME 和 JRE_HOME 变量作为相应的 Java 8 个位置,然后 运行 Tomcat [=16= .sh 和 bin/startup.sh 按顺序排列。这解决了问题。

如果将应用程序部署到可操作的 Tomcat,则可以编辑 /etc/default/tomcat8 文件以设置 JAVA_HOME,因为 OS 上的默认值可能是版本错误。

底线是小心假设 Tomcat 会在系统上找到正确的 Java 版本。