An issue is raised when an operation that closes an archive entry is called immediately after an operation that opens or begins a new entry in an archive output stream, without writing any content in between.

In Java, this specifically refers to calling closeEntry() immediately after putNextEntry() on a ZipOutputStream or JarOutputStream.

Why is this an issue?

When creating archive files (ZIP or JAR), entries are added using a three-step process:

  1. Call an API method to declare the start of a new entry
  2. Write the entry’s content using output stream methods
  3. Call an API method to finalize the entry

Skipping the second step creates an empty entry in the archive. This is almost always a mistake.

Empty archive entries serve no useful purpose. In ZIP files, they waste space by storing metadata for entries with no content. In JAR files, empty entries can cause runtime errors when the application expects to load classes or resources that don’t exist.

This pattern typically occurs due to:

Since specialized archive output streams (like those for JAR files) typically extend the base archive stream class, multiple archive types are subject to this issue.

In Java, these operations correspond to putNextEntry() to start an entry, write() methods to add content, and closeEntry() to finalize it. Both ZipOutputStream and JarOutputStream (which extends ZipOutputStream) use this API.

What is the potential impact?

Empty archive entries can cause several problems:

How to fix it

Write content to the archive entry between putNextEntry() and closeEntry() using the write() method. The content can come from a byte array, file, or any other source.

Code examples

Noncompliant code example

ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("archive.zip"));
zos.putNextEntry(new ZipEntry("empty.txt"));
zos.closeEntry(); // Noncompliant - no content written

Compliant solution

ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("archive.zip"));
zos.putNextEntry(new ZipEntry("file.txt"));
zos.write("Hello, World!".getBytes());
zos.closeEntry();

Resources

Documentation