空指针异常 Java

7

首先,我是一名经验丰富的程序员,但对Java并不熟悉。八年前我有大约两年的Java编程经验。

以下代码导致了NullPointerException错误:

public static void handle(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException {

    Response gfexResponse = null;

    try {

        ActionFactory actionFactory = ActionFactory.getInstance();
        String requestURL = request.getRequestURI();
        String actionId = actionFactory.getActionId(requestURL);

        IAction action = actionFactory.createAction(actionId);

        ActionEvent event = new ActionEvent(request, 0, actionId);
        gfexResponse = action.execute(event);

    } catch (Exception ex) {        
        gfexResponse = new Response();
        gfexResponse.setError(ex.getMessage());
        gfexResponse.setOutcome(IViewConstants.ERROR);

    } finally {

        if(request.getParameter("loginId") != null){
            request.setAttribute("loginId", request.getParameter("loginId"));
        }

        if(gfexResponse.getMessage()!= null){
            request.setAttribute("message", gfexResponse.getMessage());
        }

        if(gfexResponse.getError()!= null){
            request.setAttribute("error", gfexResponse.getError());
        }

        if (gfexResponse.getContentType() != null) {
            response.setContentType(gfexResponse.getContentType());
            OutputStream outputStream = response.getOutputStream();
            outputStream.write(gfexResponse.getOutputData());
            outputStream.flush();
            outputStream.close();
        }

        if(gfexResponse.getOutcome() != null){
            RequestDispatcher dispatcher = request.getRequestDispatcher(gfexResponse.getOutcome());
            dispatcher.forward(request, response);
        }
    }       
}

以下是 StackTrace:

[6/18/13 17:10:04:518 GMT] 00000023 ServletWrappe E   SRVE0068E: Uncaught exception thrown in one of the service methods of the servlet: GfexServlet. Exception thrown : java.lang.NullPointerException
    at com.svl.gfex.handlers.RequestHandler.handle(RequestHandler.java:44)
    at com.svl.gfex.servlets.GfexServlet.processRequest(GfexServlet.java:43)
    at com.svl.gfex.servlets.GfexServlet.doPost(GfexServlet.java:39)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:763)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:966)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:907)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:118)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:87)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:701)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:646)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:475)
    at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:463)
    at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3129)
    at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:238)
    at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:811)
    at com.ibm.ws.wswebcontainer.WebContainer.handleRequest(WebContainer.java:1433)
    at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:93)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:465)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:394)
    at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:102)
    at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:152)
    at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:213)
    at com.ibm.io.async.AbstractAsyncFuture.fireCompletionActions(AbstractAsyncFuture.java:195)
    at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:136)
    at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:194)
    at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:741)
    at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:863)
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1510)

堆栈跟踪指向此行:

        if(gfexResponse.getMessage()!= null){  <-------- this line
            request.setAttribute("message", gfexResponse.getMessage());
        }

这段代码之前是由一个海外承包商维护的,但公司解雇了所有承包商。出于我的罪过,我被安排负责修复它。

如果有人能帮我找出为什么出现这个错误,我将不胜感激。


2
添加一个检查以查看 gfexResponse == null。在Java中,空指针异常通常很容易调试,因为您正在尝试在空对象上调用方法。 - user554546
5个回答

12

该错误表示gfexResponse对象本身为null(即在上述代码中action.execute(event)返回null,并且没有抛出异常)


1
+1 对于 action.execute(event) 的发现很好。你的回答是唯一一个解释为什么 gfexResponse 为空的。 - Vishal K

4
您的基本概述如下:
public static void handle(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException {

    Response gfexResponse = null;

    try {
        //Try to get your gfexResponse
    } catch (Exception ex) {        
        //Provide a default gfexResponse
    } finally {
        //Do some stuff with gfexResponse
    }       
}

这是不好的实践:你试图使用异常处理来控制流程。此外,你假设用于获取gfexResponse的方法在失败时会抛出异常,但显然它并没有这样做。(一些简单的调试/跟踪将直接揭示这一点。)
你应该做以下事情:
public static void handle(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException {

    Response gfexResponse = null;

    try {
        //Try to get your gfexResponse
        //Make sure you got your response object and throw SomeAppropriateException if not
        //Do some stuff with gfexResponse
    } catch (SomeAppropriateException e) {
        //properly handle this case
    } catch (Exception ex) {
        //properly handle the general case that something else failed (But you should try to be more specific)
    } finally {
        //remove any resources that might not be properly cleaned up if an exception is thrown.
    }       
}

你说得对,@Nathaniel Ford。这确实是一个不好的做法。不幸的是,这是最初的编码方式,管理层没有批准修复所有问题的支出。虽然这只是一个小网站,但原始开发人员在处理流程控制方面的方式都是一样的。 - Kevin

1

实际问题在于这一行:gfexResponse = action.execute(event);

下面这一行唯一可能出现NPE的机会就是gfexResponse为空。

if(gfexResponse.getMessage()!= null){  <-------- this line

将其改为


if(gfexResponse!=null && gfexResponse.getMessage()!= null){  <-------- this line

谢谢。我尝试了,仍然在同一点出现相同的异常。 - Kevin
你们干得好,谢谢!我对它在同一点爆炸的想法是错误的。 - Kevin

1

您确定gfexResponseaction.execute(event);(在try {}中)获得了实际值吗?我猜action.execute(event);返回null。


我想我得弄清楚如何使用调试模式。 - Kevin

1

为了解决即时的问题 - 你的action.execute(event);调用很可能返回null。然而,可以通过以下几种方式来缓解这个问题:

  • 空值检查,或者
  • try-catch块转换为自己的独立方法调用,以返回Response

从那里开始,finally块成为你方法的主要焦点,你可以在不必担心finally的情况下检查空值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接