【问题标题】:How to debug NullPointerException occurred in library code?如何调试库代码中发生的 NullPointerException?
【发布时间】: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()的这一行开始

标签: java nullpointerexception zipfile


【解决方案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 被抛出该行的唯一原因是 ezcbnamenull

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,这将很难调试。 getEntryBytesnative 方法:

private static native byte[] getEntryBytes(long jzentry, int type);

这就是我将如何进行:

  • 确定是那个特定的 zip 文件还是所有的 zip 文件。如果是那个特定的 zip 文件,请尝试重新制作它。
  • 更新您的 Java 版本,getEntryBytes 可能存在已修复的错误
  • 向 Oracle 提交错误报告

【讨论】:

【解决方案2】:

我最近遇到了同样的问题,所以我比较了JDK 1.61.7相关的zip源代码

真正的原因jdk 1.6将由constructorjzentry初始化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 时,它会抛出异常。

【讨论】:

    猜你喜欢
    • 2016-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-06
    • 2020-07-28
    • 1970-01-01
    相关资源
    最近更新 更多