Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8263924

Fixed line breaks after each 72 characters can lead to invalid manifests

XMLWordPrintable

      ADDITIONAL SYSTEM INFORMATION :
      Windows 10, Java 15.0.2

      A DESCRIPTION OF THE PROBLEM :
      I had the strange problem that after Maven created a manifest for my JAR, I could no longer use "java -cp my.jar my.MainClass". I debugged from Maven Assembly through Plexus Archiver into JRE and to my surprise found out that the values were passed on cleanly, but then a JRE class produced the invalid manifest leading to the "class not found" error when trying to start a class from the JAR.

      The JRE Manifest class inserts hard line breaks always after 72 characters, no matter if those 72 characters contain line feeds, tabs or spaces. Hence, it can happen that unwanted blank lines end up in the middle of a manifest section, making the manifest invalid. Calls like e.g. 'java -cp aspectjtools.jar org.aspectj.tools.ajc.Main' can then fail with the absolutely unexpected error 'Could not find or load main class org.aspectj.tools.ajc.Main'.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Manifest.write or the helper method wrapping the manifest line checks for existing line breaks and makes sure that during line-wrapping no invalid blank lines are inserted into the manifest. If I cannot trust the JRE class to create a valid manifest it can later read again, then whom can I trust?
      ACTUAL -
      Manifest-Version: 1.0
      Bundle-Copyright: (C) Copyright 1999-2001 Xerox Corporation,

        2002 Palo Alto Research Center, Incorporated (PARC),
      2003-
       2019 Contributors. All Rights Reserved

      Exception in thread "main" java.io.IOException: invalid header field (line 3)
      at java.base/java.util.jar.Attributes.read(Attributes.java:408)
      at java.base/java.util.jar.Manifest.read(Manifest.java:290)
      at java.base/java.util.jar.Manifest.<init>(Manifest.java:100)
      at java.base/java.util.jar.Manifest.<init>(Manifest.java:76)
      at Scratch.main(scratch_3.java:29)


      ---------- BEGIN SOURCE ----------
      import java.io.ByteArrayInputStream;
      import java.io.ByteArrayOutputStream;
      import java.io.IOException;
      import java.util.jar.Attributes;
      import java.util.jar.Manifest;

      class Scratch {
        public static void main(String[] args) throws IOException {
          // Create empty manifest
          Manifest manifest = new Manifest();
          Attributes mainAttributes = manifest.getMainAttributes();
          mainAttributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
          // Add a key which leads to an invalid manifest
          // (found exactly like that in a Maven POM, quite difficult to debug!)
          mainAttributes.put(
            new Attributes.Name("Bundle-Copyright"),
            "(C) Copyright 1999-2001 Xerox Corporation,\n" +
              "\t\t\t\t\t\t\t\t\t\t\t\t2002 Palo Alto Research Center, Incorporated (PARC),\n" +
              "\t\t\t\t\t\t\t\t\t\t\t\t2003-2019 Contributors. All Rights Reserved"
          );
          // Dump invalid manifest to console - please note the fatal blank line consisting only of tabs
          manifest.write(System.out);
          ByteArrayOutputStream out = new ByteArrayOutputStream();
          manifest.write(out);
          // Read invalid manifest -> "IOException: invalid header field (line 3)"
          ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
          new Manifest(in);
        }
      }

      ---------- END SOURCE ----------

      FREQUENCY : always


            lancea Lance Andersen
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: