JDK 9 jar tool issues - "isolated nested class" and creation of a corrupt jar

Tom Hood tom.w.hood at gmail.com
Wed Aug 9 23:50:14 UTC 2017


Hi,

I'm having a couple issues with the jar tool. Version: JDK 9 build 181
SPARC64

Since I'm typing this in, beware of typos.  I cannot copy and paste output
as my Solaris 10 box isn't permitted to access the internet.

(1) isolated nested classes trying to create a multi-release jar

In my test case (which I can't give you as it's on a different network), I
have a number of classes compiled for java 6  (javac --release 6) and then
1 compiled for both java 6 and java 9.  The java 9 version is in a "v9"
subdirectory.

The complete directory structure looks likes this:

./v9/com/thirdparty/jdk/JdkSpecificClass.class
./com/thirdparty/jdk/JdkSpecificClass.class
./com/thirdparty/animation/CustomAnimation.class
./com/thirdparty/animation/CustomAnimation$0.class
./com/thirdparty/animation/CustomAnimation$BackgroundPanel.class
./com/thirdparty/animation/CustomAnimation$Callback.class
./com/thirdparty/animation/CustomAnimation$n_.class
./com/thirdparty/animation/CustomAnimation$1.class
./com/thirdparty/animation/CustomAnimation$2.class
./com/thirdparty/animation/CustomAnimation$3.class
./com/thirdparty/animation/CustomAnimation$3$0.class
./com/thirdparty/animation/CustomAnimation$3$1.class
./com/thirdparty/animation/CustomAnimation$4.class
./com/thirdparty/animation/CustomAnimation$4$0.class
./com/thirdparty/animation/CustomAnimation$4$1.class
./com/thirdparty/animation/CustomAnimation$5.class
./com/thirdparty/animation/CustomAnimation$6.class
./com/thirdparty/animation/CustomAnimation$7.class
./com/thirdparty/animation/CustomAnimation$8.class
./com/thirdparty/animation/CustomAnimation$9.class
./com/thirdparty/animation/CustomAnimation$10.class
./com/thirdparty/animation/CustomAnimation$11.class
./com/thirdparty/animation/CustomAnimation$12.class
./com/thirdparty/animation/CustomAnimation$12$1.class
./com/thirdparty/animation/CustomAnimation$12$2.class
./com/thirdparty/animation/CustomAnimation$13.class
./com/thirdparty/animation/CustomAnimation$13$1.class
./com/thirdparty/animation/CustomAnimation$13$2.class

>From that directory, I run the following jar command:

  jar cvf test.jar com --release 9 -C v9 com

It outputs the following:  (I'm not typing the "(in = N) (out= M)(deflated
P%)" text..if you need it, let me know)

added manifest
adding: com/
adding: com/thirdparty/
adding: com/thirdparty/animation/
adding: com/thirdparty/animation/CustomAnimation$0.class # should
CustomAnimation.class go first?
adding: com/thirdparty/animation/CustomAnimation$1.class
adding: com/thirdparty/animation/CustomAnimation$10.class
adding: com/thirdparty/animation/CustomAnimation$11.class
adding: com/thirdparty/animation/CustomAnimation$12$1.class  # should
CustomAnimation$12.class go first?
adding: com/thirdparty/animation/CustomAnimation$12$2.class
adding: com/thirdparty/animation/CustomAnimation$12.class
adding: com/thirdparty/animation/CustomAnimation$13$1.class  #should
CustomAnimation$13.class go first?
adding: com/thirdparty/animation/CustomAnimation$13$2.class
adding: com/thirdparty/animation/CustomAnimation$13.class
adding: com/thirdparty/animation/CustomAnimation$2.class
adding: com/thirdparty/animation/CustomAnimation$3$0.class #ditto above
comment
adding: com/thirdparty/animation/CustomAnimation$3$1.class
adding: com/thirdparty/animation/CustomAnimation$3.class
adding: com/thirdparty/animation/CustomAnimation$4$0.class #ditto above
comment
adding: com/thirdparty/animation/CustomAnimation$4$1.class
adding: com/thirdparty/animation/CustomAnimation$4.class
adding: com/thirdparty/animation/CustomAnimation$5.class
adding: com/thirdparty/animation/CustomAnimation$6.class
adding: com/thirdparty/animation/CustomAnimation$7.class
adding: com/thirdparty/animation/CustomAnimation$8.class
adding: com/thirdparty/animation/CustomAnimation$9.class
adding: com/thirdparty/animation/CustomAnimation$BackgroundPanel.class
adding: com/thirdparty/animation/CustomAnimation$Callback.class
adding: com/thirdparty/animation/CustomAnimation$n_.class
adding: com/thirdparty/animation/CustomAnimation.class
adding: com/thirdparty/jdk/
adding: com/thirdparty/jdk/JdkSpecificClass.class
adding: META-INF/versions/9/com/
adding: META-INF/versions/9/com/thirdparty/
adding: META-INF/versions/9/com/thirdparty/jdk/
adding: META-INF/versions/9/com/thirdparty/jdk/JdkSpecificClass.class
entry: com/thirdparty/animation/CustomAnimation$12$1.class, is an isolated
nested class
entry: com/thirdparty/animation/CustomAnimation$12$2.class, is an isolated
nested class
entry: com/thirdparty/animation/CustomAnimation$13$1.class, is an isolated
nested class
entry: com/thirdparty/animation/CustomAnimation$13$2.class, is an isolated
nested class
entry: com/thirdparty/animation/CustomAnimation$3$0.class, is an isolated
nested class
entry: com/thirdparty/animation/CustomAnimation$3$1.class, is an isolated
nested class
entry: com/thirdparty/animation/CustomAnimation$4$0.class, is an isolated
nested class
entry: com/thirdparty/animation/CustomAnimation$4$1.class, is an isolated
nested class
invalid multi-release jar file test.jar deleted

I then thought I might be able to control the order of the adds via an
@classlist file.  It didn't help.  I looked at the jdk source
jdk.jartool/sun/tools/jar/Validator.jar and found that it sorts the class
files so top level classes are supposed to come before nested ones (see
ENTRYNAME_COMPARATOR).  I looked briefly at it and didn't notice a bug, but
someone more familiar with the jar tool code should probably take a look.

I also added a -J-Djar.debug=true to the jar command line hoping for some
insight...didn't get any.  If you need that output, let me know.

I then thought, OK, let me add the toplevel classes first, then update the
jar with the nested classes using a separate "jar uvf".  That's when I hit
issue (2), because the "jar uvf" command was unable to read the jar just
created, although "jar tvf" could read it okay.

(2) creation of a corrupt jar on SPARC64

I suspect this might be related to JDK-8062911
<https://bugs.openjdk.java.net/browse/JDK-8062911> which was closed saying
the submitter had a workaround to change the zip read buffer size.

Is there a way to specify different zip buffer sizes to the jar command?

The jar command I ran was:

    jar cvf test.jar @classlist.toplevel --release 9 -C v9 com

The file "classlist.toplevel" contains only the top level class files (no
"$" signs)

That appeared to work and create the jar.  jar tvf test.jar shows the
correct files.

However, jar xvf test.jar gives me this output:

  created: META-INF/
java.io.IOExeption: Push back buffer is full
    at
java.base/java.io.PushbackIinputStream.unread(PushbackInputStream.java:229)
    at
java.base/java.util.zip.ZipInputStream.readEnd(ZipInputStream.java:359)
    at java.base/java.util.zip.ZipInputStream.read(ZipInputStream.java:197)
    at
java.base/java.util.zip.ZipInputStream.closeEntry(ZipInputStream.java:141)
    at jdk.jartool/sun.tools.jar.Main.extractFile(Main.java:1446)
    at jdk.jartool/sun.tools.jar.Main.extract(Main.java:1353)
    at jdk.jartool/sun.tools.jar.Main.run(Main.java:403)
    at jdk.jartool/sun.tools.jar.Main.main(Main.java:1670)

The only file left over from the failed extraction was the
META-INF/MANIFEST.MF which contained:
  Manifest-Version: 1.0
  Created-By: 9 (Oracle Corporation)
  Multi-Release: true

*Windows 7 Testing*

I copied the test.jar file and class directory tree from my solaris sparc
box to a windows 7 box and installed the 64-bit windows version of JDK 9
build 181.

I first tried to "jar xvf test.jar" to see if the windows jar tool could
read the test.jar created using the SPARC64 jar tool.  It couldn't and
failed with the same stack trace with the java.io.IOException.

I then ran the same jar create command using the windows jar tool.  It
worked and I was able to extract the files on windows.

I was then able to update that jar and add the nested classes via an
@classlist.level1 file that just contained the nested class files (one $
sign).  Finally I was able to update it further with an @classlist.level2
file that had the nested nested classes (two $ signs).

Pushing my luck, I tried to start over and run my original jar creation
command on windows, but it failed the same way it did for the SPARC64 jar
tool with the "isolated nested class" errors.

I also tried creating the jar file with a combined file with classes from
classlist.toplevel and classlist.level1.  That worked and I was able to
update the jar with the classlist.level2.

Let me know what else you need to reproduce this.

Thanks,
-- Tom


More information about the core-libs-dev mailing list