From d51a58ec2e1ce26c056c75256d6c75e330eafd9c Mon Sep 17 00:00:00 2001 From: ksrini Date: Sat, 19 Jun 2010 17:42:39 -0700 Subject: [PATCH] 6712743: pack200: should default to 150.7 pack format for classfiles without any classes. Reviewed-by: jrose --- .../com/sun/java/util/jar/pack/Constants.java | 7 +- .../com/sun/java/util/jar/pack/Package.java | 17 +- src/share/classes/java/util/jar/Pack200.java | 16 +- test/tools/pack200/PackageVersionTest.java | 169 ++++++++++++++++++ 4 files changed, 196 insertions(+), 13 deletions(-) create mode 100644 test/tools/pack200/PackageVersionTest.java diff --git a/src/share/classes/com/sun/java/util/jar/pack/Constants.java b/src/share/classes/com/sun/java/util/jar/pack/Constants.java index a9deb0cd8..19ce04cf5 100644 --- a/src/share/classes/com/sun/java/util/jar/pack/Constants.java +++ b/src/share/classes/com/sun/java/util/jar/pack/Constants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,10 +47,13 @@ interface Constants { public final static short JAVA5_MAX_CLASS_MAJOR_VERSION = 49; public final static short JAVA5_MAX_CLASS_MINOR_VERSION = 0; - // NOTE: ASSUMED for now + public final static short JAVA6_MAX_CLASS_MAJOR_VERSION = 50; public final static short JAVA6_MAX_CLASS_MINOR_VERSION = 0; + public final static short JAVA7_MAX_CLASS_MAJOR_VERSION = 51; + public final static short JAVA7_MAX_CLASS_MINOR_VERSION = 0; + public final static int JAVA_PACKAGE_MAGIC = 0xCAFED00D; public final static int JAVA5_PACKAGE_MAJOR_VERSION = 150; public final static int JAVA5_PACKAGE_MINOR_VERSION = 7; diff --git a/src/share/classes/com/sun/java/util/jar/pack/Package.java b/src/share/classes/com/sun/java/util/jar/pack/Package.java index ad7fdbaa5..1ea04690e 100644 --- a/src/share/classes/com/sun/java/util/jar/pack/Package.java +++ b/src/share/classes/com/sun/java/util/jar/pack/Package.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,8 +57,8 @@ class Package implements Constants { // These fields can be adjusted by driver properties. short min_class_majver = JAVA_MIN_CLASS_MAJOR_VERSION; short min_class_minver = JAVA_MIN_CLASS_MINOR_VERSION; - short max_class_majver = JAVA6_MAX_CLASS_MAJOR_VERSION; - short max_class_minver = JAVA6_MAX_CLASS_MINOR_VERSION; + short max_class_majver = JAVA7_MAX_CLASS_MAJOR_VERSION; + short max_class_minver = JAVA7_MAX_CLASS_MINOR_VERSION; short observed_max_class_majver = min_class_majver; short observed_max_class_minver = min_class_minver; @@ -122,13 +122,16 @@ class Package implements Constants { void choosePackageVersion() { assert(package_majver <= 0); // do not call this twice int classver = getHighestClassVersion(); - if (classver != 0 && - (classver >>> 16) < JAVA6_MAX_CLASS_MAJOR_VERSION) { - // There are only old classfiles in this segment. + if (classver == 0 || (classver >>> 16) < JAVA6_MAX_CLASS_MAJOR_VERSION) { + // There are only old classfiles in this segment or resources package_majver = JAVA5_PACKAGE_MAJOR_VERSION; package_minver = JAVA5_PACKAGE_MINOR_VERSION; + } else if ((classver >>> 16) == JAVA6_MAX_CLASS_MAJOR_VERSION) { + package_majver = JAVA6_PACKAGE_MAJOR_VERSION; + package_minver = JAVA6_PACKAGE_MINOR_VERSION; } else { - // Normal case. Use the newest archive format. + // Normal case. Use the newest archive format, when available + // TODO: replace the following with JAVA7* when the need arises package_majver = JAVA6_PACKAGE_MAJOR_VERSION; package_minver = JAVA6_PACKAGE_MINOR_VERSION; } diff --git a/src/share/classes/java/util/jar/Pack200.java b/src/share/classes/java/util/jar/Pack200.java index 1f126f7ba..41dec9180 100644 --- a/src/share/classes/java/util/jar/Pack200.java +++ b/src/share/classes/java/util/jar/Pack200.java @@ -212,10 +212,18 @@ public abstract class Pack200 { * to produce a specific bytewise image for any given transmission * ordering of archive elements.) *

- * In order to maintain backward compatibility, if the input JAR-files are - * solely comprised of 1.5 (or lesser) classfiles, a 1.5 compatible - * pack file is produced. Otherwise a 1.6 compatible pack200 file is - * produced. + * In order to maintain backward compatibility, the pack file's version is + * set to accommodate the class files present in the input JAR file. In + * other words, the pack file version will be the latest, if the class files + * are the latest and conversely the pack file version will be the oldest + * if the class file versions are also the oldest. For intermediate class + * file versions the corresponding pack file version will be used. + * For example: + * If the input JAR-files are solely comprised of 1.5 (or lesser) + * class files, a 1.5 compatible pack file is produced. This will also be + * the case for archives that have no class files. + * If the input JAR-files contains a 1.6 class file, then the pack file + * version will be set to 1.6. *

* @since 1.5 */ diff --git a/test/tools/pack200/PackageVersionTest.java b/test/tools/pack200/PackageVersionTest.java new file mode 100644 index 000000000..0cd9ca264 --- /dev/null +++ b/test/tools/pack200/PackageVersionTest.java @@ -0,0 +1,169 @@ + +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6712743 + * @summary verify package versioning + * @compile -XDignore.symbol.file PackageVersionTest.java + * @run main PackageVersionTest + */ + +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.jar.JarFile; +import java.util.jar.Pack200; +import java.util.jar.Pack200.Packer; + +public class PackageVersionTest { + private static final File javaHome = new File(System.getProperty("java.home")); + + public final static int JAVA5_PACKAGE_MAJOR_VERSION = 150; + public final static int JAVA5_PACKAGE_MINOR_VERSION = 7; + + public final static int JAVA6_PACKAGE_MAJOR_VERSION = 160; + public final static int JAVA6_PACKAGE_MINOR_VERSION = 1; + + public static void main(String... args) { + if (!javaHome.getName().endsWith("jre")) { + throw new RuntimeException("Error: requires an SDK to run"); + } + + File out = new File("test.pack"); + createClassFile("Test5"); + createClassFile("Test6"); + createClassFile("Test7"); + + verifyPack("Test5.class", JAVA5_PACKAGE_MAJOR_VERSION, + JAVA5_PACKAGE_MINOR_VERSION); + + verifyPack("Test6.class", JAVA6_PACKAGE_MAJOR_VERSION, + JAVA6_PACKAGE_MINOR_VERSION); + + // TODO: change this to the java7 package version as needed. + verifyPack("Test7.class", JAVA6_PACKAGE_MAJOR_VERSION, + JAVA6_PACKAGE_MINOR_VERSION); + + // test for resource file, ie. no class files + verifyPack("Test6.java", JAVA5_PACKAGE_MAJOR_VERSION, + JAVA5_PACKAGE_MINOR_VERSION); + } + + static void close(Closeable c) { + if (c == null) { + return; + } + try { + c.close(); + } catch (IOException ignore) {} + } + + static void createClassFile(String name) { + createJavaFile(name); + String target = name.substring(name.length() - 1); + String javacCmds[] = { + "-source", + "5", + "-target", + name.substring(name.length() - 1), + name + ".java" + }; + compileJava(javacCmds); + } + + static void createJavaFile(String name) { + PrintStream ps = null; + FileOutputStream fos = null; + File outputFile = new File(name + ".java"); + outputFile.delete(); + try { + fos = new FileOutputStream(outputFile); + ps = new PrintStream(fos); + ps.format("public class %s {}", name); + } catch (IOException ioe) { + throw new RuntimeException("creation of test file failed"); + } finally { + close(ps); + close(fos); + } + } + + static void compileJava(String... javacCmds) { + if (com.sun.tools.javac.Main.compile(javacCmds) != 0) { + throw new RuntimeException("compilation failed"); + } + } + + static void makeJar(String... jargs) { + sun.tools.jar.Main jarTool = + new sun.tools.jar.Main(System.out, System.err, "jartool"); + if (!jarTool.run(jargs)) { + throw new RuntimeException("jar command failed"); + } + } + + static void verifyPack(String filename, int expected_major, int expected_minor) { + + File jarFileName = new File("test.jar"); + jarFileName.delete(); + String jargs[] = { + "cvf", + jarFileName.getName(), + filename + }; + makeJar(jargs); + JarFile jfin = null; + + try { + jfin = new JarFile(jarFileName); + Packer packer = Pack200.newPacker(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + packer.pack(jfin, baos); + baos.flush(); + baos.close(); + byte[] buf = baos.toByteArray(); + + int minor = buf[4] & 0x000000ff; + int major = buf[5] & 0x000000ff; + + if (major != expected_major || minor != expected_minor) { + String msg = + String.format("test fails: expected:%d.%d but got %d.%d\n", + expected_major, expected_minor, + major, minor); + throw new Error(msg); + } + + System.out.println(filename + ": OK"); + } catch (IOException ioe) { + throw new RuntimeException(ioe.getMessage()); + } finally { + close(jfin); + } + } +} -- GitLab