枚举空指针异常?

时间:2016-05-27 23:14:24

标签: java nullpointerexception http-headers request enumeration

您好我正在使用HttpServletRequest并尝试设置标头集。

以下是代码:

public static Map<String, String> getHeaders(HttpServletRequest request) { 
   Map<String, String> headers = new HashMap<String, String>();

  Enumeration<String> headerNames = request.getHeaderNames(); 
  if (headerNames != null) {
            while (headerNames.hasMoreElements()) {
                String headerName = headerNames.nextElement();
                String header = request.getHeader(headerName);
                headers.put(headerName, header);
            }
        }
        return headers;

}

此方法似乎在headerNames.nextElement()中抛出Null指针异常。

hasMoreElements检查是否可能返回true,但是元素headerNames.nextElement又导致空指针异常?

堆栈追踪:

    Stack trace : Caused by: java.lang.NullPointerException at org.apache.tomcat.util.buf.ByteChunk.equalsIgnoreCase(ByteChunk.java:608) at 
org.apache.tomcat.util.buf.MessageBytes.equalsIgnoreCase(MessageBytes.java:325) 
at org.apache.tomcat.util.http.NamesEnumerator.findNext(MimeHeaders.java:414) at org.apache.tomcat.util.http.NamesEnumerator.nextElement(MimeHeaders.java:438) 
at org.apache.tomcat.util.http.NamesEnumerator.nextElement(MimeHeaders.java:396) at generateRequestHeaderMap...

如果你们能帮助我解决这个问题,那将是很棒的。

2 个答案:

答案 0 :(得分:1)

我怀疑问题是由错误的请求引起的。以下是findNext()正在做的事情(在Tomcat 6.0.18中):

private void  findNext() {
    next=null;
    for(  ; pos< size; pos++ ) {
        next=headers.getName( pos ).toString();
        for( int j=0; j<pos ; j++ ) {
            if( headers.getName( j ).equalsIgnoreCase( next )) {
                // duplicate.
                next=null;
                break;
            }
        }
        if( next!=null ) {
            // it's not a duplicate
            break;
        }
    }
    // next time findNext is called it will try the
    // next element
    pos++;
}

重点是:

next=headers.getName( pos ).toString();

if( headers.getName( j ).equalsIgnoreCase( next )) {

如果标头被破坏,则getName(j)可能会返回null。如果发生这种情况,那么ByteChunk方法的equalsIgnoreCase路径将抛出NPE。

如果你要科学地追踪这一点,你需要:

  • 获取请求的实际原始字节,并在法律上检查它们以确定损坏的性质(如果有)
  • 设置一个测试工具,允许您使用附加的调试器在此请求上运行您的应用程序....并在源头捕获该异常。

非科学方法是将Tomcat升级到Tomcat 6 ...或更高版本的最新补丁版本。它可能会解决问题。或者不是。

此处有关于2010年之后Tomcat 6.0.20中此问题的另一个报告:

答案 1 :(得分:0)

这就是我基于Apache Tomcat 6.0.20源代码在JBoss 6.1.0 Final(在deploy / jbossweb.sar / jbossweb.jar中)成功修补Apache Tomcat的方法:

org.apache.tomcat.util.http.MimeHeaders.NamesEnumerator.findNext()

    private void findNext() {
        next=null;
        for(  ; pos< size; pos++ ) {
            // (4 lines changed): check mb for null as suggested here: https://stackoverflow.com/questions/37493552/enumeration-null-pointer-exception/37493888#37493888
            MessageBytes mb = headers.getName( pos );
            if (mb != null) {
                next=mb.toString();
            }
            for( int j=0; j<pos ; j++ ) {
                // (2 lines changed): check mb and nex for null as suggested here: https://stackoverflow.com/questions/37493552/enumeration-null-pointer-exception/37493888#37493888
                mb = headers.getName( j );
                if(mb != null && next != null && mb.equalsIgnoreCase( next )) {
                    // duplicate.
                    next=null;
                    break;
                }
            }
            // new (just 1 comment line): if mb == null we assume next == null, thus it will be a duplicate (i.e. not found, causing no break)
            if( next!=null ) {
                // it's not a duplicate
                break;
            }
        }
        // next time findNext is called it will try the
        // next element
        pos++;
    }

当然,它不会避免https://mail-archives.apache.org/mod_mbox/tomcat-users/201002.mbox/%3c27699460.post@talk.nabble.com%3e中提到的非线程安全实现,但至少在读取不必要的头文件时避免了NullPointerException。