您好我正在使用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...
如果你们能帮助我解决这个问题,那将是很棒的。
答案 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。