如何调试库代码中发生的 NullPointerException?
Posted
技术标签:
【中文标题】如何调试库代码中发生的 NullPointerException?【英文标题】:How to debug NullPointerException occurred in library code? 【发布时间】:2013-02-21 02:33:50 【问题描述】:我正在用 java 解压一个 ZIP 文件:
ZipFile zipFile = new ZipFile(theZipFile);
Enumeration<? extends ZipEntry> zipEntries = zipFile.entries();
while(zipEntries.hasMoreElements())
ZipEntry entry = zipEntries.nextElement(); /// <---Nullpointer exception happens here
代码执行超过while(zipEntries.hasMoreElements())
,但未能提取 ZipEntry。
奇怪的是hasMoreElements
返回true,但是尝试取出元素时出现空指针。
异常来自 JDK lib 的 ZipFile 类,我在调试器中看不到局部变量,那么如何找出 Zip 文件的问题?
编辑: 堆栈跟踪:
java.lang.NullPointerException
at java.util.zip.ZipFile.getZipEntry(ZipFile.java:529)
at java.util.zip.ZipFile.access$900(ZipFile.java:56)
at java.util.zip.ZipFile$1.nextElement(ZipFile.java:511)
at java.util.zip.ZipFile$1.nextElement(ZipFile.java:481)
【问题讨论】:
请发布堆栈跟踪。另外,在您处理文件时是否有可能修改文件? 如果你附加了一个调试器,你检查过 zipEntries 的值吗?检查 zipEntries 上的元素怎么样? @TedHopp 堆栈跟踪已添加。不,文件在解压过程中没有被修改。 这是整个堆栈跟踪吗?那里没有你的代码。 @TedHopp 从我的帖子ZipEntry entry = zipEntries.nextElement()
的这一行开始
【参考方案1】:
这里是 getZipEntry
方法(截至 1.7.0_10):
private ZipEntry getZipEntry(String name, long jzentry)
ZipEntry e = new ZipEntry();
e.flag = getEntryFlag(jzentry); // get the flag first
if (name != null)
e.name = name;
else
byte[] bname = getEntryBytes(jzentry, JZENTRY_NAME);
if (!zc.isUTF8() && (e.flag & EFS) != 0)
e.name = zc.toStringUTF8(bname, bname.length);
else
e.name = zc.toString(bname, bname.length); // Line 529
/* snip */
return e;
NullPointerException
被抛出该行的唯一原因是 e
、zc
或 bname
是 null
。
e
不能是null
,因为在这个方法中明确实例化了。
zc
不能是null
:
public ZipFile(File file, int mode, Charset charset) throws IOException
/* snip */
this.zc = ZipCoder.get(charset);
/* snip */
static ZipCoder get(Charset charset)
return new ZipCoder(charset);
这意味着bname
必须是null
,这将很难调试。 getEntryBytes
是 native
方法:
private static native byte[] getEntryBytes(long jzentry, int type);
这就是我将如何进行:
确定是那个特定的 zip 文件还是所有的 zip 文件。如果是那个特定的 zip 文件,请尝试重新制作它。 更新您的 Java 版本,getEntryBytes
可能存在已修复的错误
向 Oracle 提交错误报告
【讨论】:
好的,终于搞定了。 ZipFile 有一个名称为空字符串的条目!感谢杰弗里的详细解释! 这应该最终用 JDK9 (bugs.openjdk.java.net/browse/JDK-8048990) 解决。【参考方案2】:我最近遇到了同样的问题,所以我比较了JDK 1.6和1.7相关的zip源代码。
真正的原因是jdk 1.6将由constructor用jzentry初始化zipEntry > 像这样:
ZipEntry ze = new ZipEntry(jzentry);
ZipEntry(long jzentry)
initFields(jzentry);
但是在jdk 1.7中我们可以看到它使用
private ZipEntry getZipEntry(String name, long jzentry)
ZipEntry e = new ZipEntry(); // it did not use jzentry initial it
当某些 jar 文件有 empty entry 时,它会抛出异常。
【讨论】:
以上是关于如何调试库代码中发生的 NullPointerException?的主要内容,如果未能解决你的问题,请参考以下文章
SpringDataForCassandra:当数据库中的 Int 列设置为空时,实体中的 NullPointerEx
Failed to start bean ‘documentationPluginsBootstrapper‘; nested exception is java.lang.NullPointerEx