7168401: pack200 does not produce a compatible pack file for JDK7 classes if indy is not present
Reviewed-by: jrose
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java Tue May 29 13:16:17 2012 -0700
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java Tue May 29 14:56:48 2012 -0700
@@ -653,8 +653,8 @@
return fixups[0]; // return ref-bearing cookie, if any
}
- public String layoutForPackageMajver(int majver) {
- if (majver <= JAVA5_PACKAGE_MAJOR_VERSION) {
+ public String layoutForClassVersion(Package.Version vers) {
+ if (vers.lessThan(JAVA6_MAX_CLASS_VERSION)) {
// Disallow layout syntax in the oldest protocol version.
return expandCaseDashNotation(layout);
}
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java Tue May 29 13:16:17 2012 -0700
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java Tue May 29 14:56:48 2012 -0700
@@ -74,30 +74,27 @@
abstract protected Index getCPIndex(byte tag);
- // Local copy of package version.
- private int packageMajver = -1;
+ // Local copy of highest class version.
+ private Package.Version highestClassVersion = null;
/** Call this exactly once, early, to specify the archive major version. */
- public void initPackageMajver(int packageMajver) throws IOException {
- assert(packageMajver > 0 && packageMajver < 0x10000);
- if (this.packageMajver > 0) {
+ public void initHighestClassVersion(Package.Version highestClassVersion) throws IOException {
+ if (this.highestClassVersion != null) {
throw new IOException(
- "Package majver is already initialized to " + this.packageMajver+
- "; new setting is " + packageMajver);
+ "Highest class major version is already initialized to " +
+ this.highestClassVersion + "; new setting is " + highestClassVersion);
}
- this.packageMajver = packageMajver;
- adjustToMajver();
+ this.highestClassVersion = highestClassVersion;
+ adjustToClassVersion();
}
- public int getPackageMajver() {
- if (packageMajver < 0) {
- throw new RuntimeException("Package majver not yet initialized");
- }
- return packageMajver;
+
+ public Package.Version getHighestClassVersion() {
+ return highestClassVersion;
}
private final boolean isReader = this instanceof PackageReader;
- protected BandStructure() {
- }
+
+ protected BandStructure() {}
final static Coding BYTE1 = Coding.of(1,256);
@@ -1866,20 +1863,12 @@
attrClassFileVersionMask = (1<<CLASS_ATTR_ClassFile_version);
}
- private void adjustToMajver() throws IOException {
- if (getPackageMajver() < JAVA6_PACKAGE_MAJOR_VERSION) {
+ private void adjustToClassVersion() throws IOException {
+ if (getHighestClassVersion().lessThan(JAVA6_MAX_CLASS_VERSION)) {
if (verbose > 0) Utils.log.fine("Legacy package version");
// Revoke definition of pre-1.6 attribute type.
undefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE);
}
- if (getPackageMajver() < JAVA7_PACKAGE_MAJOR_VERSION) {
- if (testBit(archiveOptions, AO_HAVE_CP_EXTRAS))
- // this bit was reserved for future use in previous versions
- throw new IOException("Format bits for Java 7 must be zero in previous releases");
- }
- if (testBit(archiveOptions, AO_UNUSED_MBZ)) {
- throw new IOException("High archive option bits are reserved and must be zero: "+Integer.toHexString(archiveOptions));
- }
}
protected void initAttrIndexLimit() {
@@ -1942,21 +1931,14 @@
}
}
- protected Attribute makeClassFileVersionAttr(int minver, int majver) {
- byte[] bytes = {
- (byte)(minver >> 8), (byte)minver,
- (byte)(majver >> 8), (byte)majver
- };
- return attrClassFileVersion.addContent(bytes);
+ protected Attribute makeClassFileVersionAttr(Package.Version ver) {
+ return attrClassFileVersion.addContent(ver.asBytes());
}
- protected short[] parseClassFileVersionAttr(Attribute attr) {
+ protected Package.Version parseClassFileVersionAttr(Attribute attr) {
assert(attr.layout() == attrClassFileVersion);
assert(attr.size() == 4);
- byte[] bytes = attr.bytes();
- int minver = ((bytes[0] & 0xFF) << 8) | (bytes[1] & 0xFF);
- int majver = ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF);
- return new short[]{ (short) minver, (short) majver };
+ return Package.Version.of(attr.bytes());
}
private boolean assertBandOKForElems(Band[] ab, Attribute.Layout.Element[] elems) {
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java Tue May 29 13:16:17 2012 -0700
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java Tue May 29 14:56:48 2012 -0700
@@ -174,27 +174,31 @@
("Bad magic number in class file "
+Integer.toHexString(cls.magic),
ATTR_CONTEXT_CLASS, "magic-number", "pass");
- cls.minver = (short) readUnsignedShort();
- cls.majver = (short) readUnsignedShort();
+ int minver = (short) readUnsignedShort();
+ int majver = (short) readUnsignedShort();
+ cls.version = Package.Version.of(majver, minver);
+
//System.out.println("ClassFile.version="+cls.majver+"."+cls.minver);
- String bad = checkVersion(cls.majver, cls.minver);
+ String bad = checkVersion(cls.version);
if (bad != null) {
throw new Attribute.FormatException
("classfile version too "+bad+": "
- +cls.majver+"."+cls.minver+" in "+cls.file,
+ +cls.version+" in "+cls.file,
ATTR_CONTEXT_CLASS, "version", "pass");
}
}
- private String checkVersion(int majver, int minver) {
- if (majver < pkg.min_class_majver ||
- (majver == pkg.min_class_majver &&
- minver < pkg.min_class_minver)) {
+ private String checkVersion(Package.Version ver) {
+ int majver = ver.major;
+ int minver = ver.minor;
+ if (majver < pkg.minClassVersion.major ||
+ (majver == pkg.minClassVersion.major &&
+ minver < pkg.minClassVersion.minor)) {
return "small";
}
- if (majver > pkg.max_class_majver ||
- (majver == pkg.max_class_majver &&
- minver > pkg.max_class_minver)) {
+ if (majver > pkg.maxClassVersion.major ||
+ (majver == pkg.maxClassVersion.major &&
+ minver > pkg.maxClassVersion.minor)) {
return "large";
}
return null; // OK
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassWriter.java Tue May 29 13:16:17 2012 -0700
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassWriter.java Tue May 29 14:56:48 2012 -0700
@@ -113,8 +113,8 @@
void writeMagicNumbers() throws IOException {
writeInt(cls.magic);
- writeShort(cls.minver);
- writeShort(cls.majver);
+ writeShort(cls.version.minor);
+ writeShort(cls.version.major);
}
void writeConstantPool() throws IOException {
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java Tue May 29 13:16:17 2012 -0700
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java Tue May 29 14:56:48 2012 -0700
@@ -43,30 +43,40 @@
1.0 to 1.3.X 45,3
1.4 to 1.4.X 46,0
1.5 to 1.5.X 49,0
- 1.6 to 1.5.x 50,0 NOTE Assumed for now
+ 1.6 to 1.5.x 50,0
+ 1.7 to 1.6.x 51,0
*/
- public final static short JAVA_MIN_CLASS_MAJOR_VERSION = 45;
- public final static short JAVA_MIN_CLASS_MINOR_VERSION = 03;
+ public final static Package.Version JAVA_MIN_CLASS_VERSION =
+ Package.Version.of(45, 03);
- public final static short JAVA5_MAX_CLASS_MAJOR_VERSION = 49;
- public final static short JAVA5_MAX_CLASS_MINOR_VERSION = 0;
+ public final static Package.Version JAVA5_MAX_CLASS_VERSION =
+ Package.Version.of(49, 00);
- public final static short JAVA6_MAX_CLASS_MAJOR_VERSION = 50;
- public final static short JAVA6_MAX_CLASS_MINOR_VERSION = 0;
+ public final static Package.Version JAVA6_MAX_CLASS_VERSION =
+ Package.Version.of(50, 00);
- public final static short JAVA7_MAX_CLASS_MAJOR_VERSION = 51;
- public final static short JAVA7_MAX_CLASS_MINOR_VERSION = 0;
+ public final static Package.Version JAVA7_MAX_CLASS_VERSION =
+ Package.Version.of(51, 00);
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;
+
+ public final static Package.Version JAVA5_PACKAGE_VERSION =
+ Package.Version.of(150, 7);
+
+ public final static Package.Version JAVA6_PACKAGE_VERSION =
+ Package.Version.of(160, 1);
- public final static int JAVA6_PACKAGE_MAJOR_VERSION = 160;
- public final static int JAVA6_PACKAGE_MINOR_VERSION = 1;
+ public final static Package.Version JAVA7_PACKAGE_VERSION =
+ Package.Version.of(170, 1);
- public final static int JAVA7_PACKAGE_MAJOR_VERSION = 170;
- public final static int JAVA7_PACKAGE_MINOR_VERSION = 1;
+ // upper limit, should point to the latest class version
+ public final static Package.Version JAVA_MAX_CLASS_VERSION =
+ JAVA7_MAX_CLASS_VERSION;
+
+ // upper limit should point to the latest package version, for version info!.
+ public final static Package.Version MAX_PACKAGE_VERSION =
+ JAVA7_PACKAGE_VERSION;
public final static int CONSTANT_POOL_INDEX_LIMIT = 0x10000;
public final static int CONSTANT_POOL_NARROW_LIMIT = 0x00100;
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Package.java Tue May 29 13:16:17 2012 -0700
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Package.java Tue May 29 14:56:48 2012 -0700
@@ -25,6 +25,7 @@
package com.sun.java.util.jar.pack;
+import java.util.jar.Pack200;
import com.sun.java.util.jar.pack.Attribute.Layout;
import com.sun.java.util.jar.pack.ConstantPool.ClassEntry;
import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry;
@@ -67,46 +68,58 @@
verbose = pmap.getInteger(Utils.DEBUG_VERBOSE);
}
- int magic;
- int package_minver;
- int package_majver;
+ final int magic = JAVA_PACKAGE_MAGIC;
int default_modtime = NO_MODTIME;
int default_options = 0; // FO_DEFLATE_HINT
- short default_class_majver = -1; // fill in later
- short default_class_minver = 0; // fill in later
+ Version defaultClassVersion = null;
// 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 = JAVA7_MAX_CLASS_MAJOR_VERSION;
- short max_class_minver = JAVA7_MAX_CLASS_MINOR_VERSION;
+ final Version minClassVersion;
+ final Version maxClassVersion;
+ // null, indicates that consensus rules during package write
+ final Version packageVersion;
- short observed_max_class_majver = min_class_majver;
- short observed_max_class_minver = min_class_minver;
+ Version observedHighestClassVersion = null;
+
// What constants are used in this unit?
ConstantPool.IndexGroup cp = new ConstantPool.IndexGroup();
- Package() {
- magic = JAVA_PACKAGE_MAGIC;
- package_minver = -1; // fill in later
- package_majver = 0; // fill in later
+ /*
+ * typically used by the PackageReader to set the defaults, in which
+ * case we take the defaults.
+ */
+ public Package() {
+ minClassVersion = JAVA_MIN_CLASS_VERSION;
+ maxClassVersion = JAVA_MAX_CLASS_VERSION;
+ packageVersion = null;
}
- public
- void reset() {
+
+ /*
+ * Typically used by the PackerImpl during before packing, the defaults are
+ * overridden by the users preferences.
+ */
+ public Package(Version minClassVersion, Version maxClassVersion, Version packageVersion) {
+ // Fill in permitted range of major/minor version numbers.
+ this.minClassVersion = minClassVersion == null
+ ? JAVA_MIN_CLASS_VERSION
+ : minClassVersion;
+ this.maxClassVersion = maxClassVersion == null
+ ? JAVA_MAX_CLASS_VERSION
+ : maxClassVersion;
+ this.packageVersion = packageVersion;
+ }
+
+
+ public void reset() {
cp = new ConstantPool.IndexGroup();
classes.clear();
files.clear();
BandStructure.nextSeqForDebug = 0;
- package_minver = -1; // fill in later
- package_majver = 0; // fill in later
- }
-
- int getPackageVersion() {
- return (package_majver << 16) + package_minver;
+ observedHighestClassVersion = null;
}
// Special empty versions of Code and InnerClasses, used for markers.
@@ -128,73 +141,31 @@
attrDefs = Collections.unmodifiableMap(ad);
}
- int getDefaultClassVersion() {
- return (default_class_majver << 16) + (char)default_class_minver;
+ Version getDefaultClassVersion() {
+ return defaultClassVersion;
}
/** Return the highest version number of all classes,
* or 0 if there are no classes.
*/
- int getHighestClassVersion() {
- int res = 0; // initial low value
+ private void setHighestClassVersion() {
+ if (observedHighestClassVersion != null)
+ return;
+ Version res = JAVA_MIN_CLASS_VERSION; // initial low value
for (Class cls : classes) {
- int ver = cls.getVersion();
- if (res < ver) res = ver;
+ Version ver = cls.getVersion();
+ if (res.lessThan(ver)) res = ver;
}
- return res;
+ observedHighestClassVersion = res;
}
- /** Convenience function to choose an archive version based
- * on the class file versions observed within the archive.
- */
- 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 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, when available
- package_majver = JAVA7_PACKAGE_MAJOR_VERSION;
- package_minver = JAVA7_PACKAGE_MINOR_VERSION;
- }
+ Version getHighestClassVersion() {
+ setHighestClassVersion();
+ return observedHighestClassVersion;
}
// What Java classes are in this unit?
- // Fixed 6211177, converted to throw IOException
- void checkVersion() throws IOException {
- if (magic != JAVA_PACKAGE_MAGIC) {
- String gotMag = Integer.toHexString(magic);
- String expMag = Integer.toHexString(JAVA_PACKAGE_MAGIC);
- throw new IOException("Unexpected package magic number: got "+gotMag+"; expected "+expMag);
- }
- int[] majminFound = null;
- for (int[] majmin : new int[][]{
- { JAVA7_PACKAGE_MAJOR_VERSION, JAVA7_PACKAGE_MINOR_VERSION },
- { JAVA6_PACKAGE_MAJOR_VERSION, JAVA6_PACKAGE_MINOR_VERSION },
- { JAVA5_PACKAGE_MAJOR_VERSION, JAVA5_PACKAGE_MINOR_VERSION }
- }) {
- if (package_majver == majmin[0] && package_minver == majmin[1]) {
- majminFound = majmin;
- break;
- }
- }
- if (majminFound == null) {
- String gotVer = package_majver+"."+package_minver;
- String expVer = JAVA7_PACKAGE_MAJOR_VERSION+"."+JAVA7_PACKAGE_MINOR_VERSION+
- " OR "+
- JAVA6_PACKAGE_MAJOR_VERSION+"."+JAVA6_PACKAGE_MINOR_VERSION+
- " OR "+
- JAVA5_PACKAGE_MAJOR_VERSION+"."+JAVA5_PACKAGE_MINOR_VERSION;
- throw new IOException("Unexpected package minor version: got "+gotVer+"; expected "+expVer);
- }
- }
-
ArrayList<Package.Class> classes = new ArrayList<>();
public List<Package.Class> getClasses() {
@@ -210,7 +181,7 @@
// File header
int magic;
- short minver, majver;
+ Version version;
// Local constant pool (one-way mapping of index => package cp).
Entry[] cpMap;
@@ -231,8 +202,7 @@
Class(int flags, ClassEntry thisClass, ClassEntry superClass, ClassEntry[] interfaces) {
this.magic = JAVA_MAGIC;
- this.minver = default_class_minver;
- this.majver = default_class_majver;
+ this.version = defaultClassVersion;
this.flags = flags;
this.thisClass = thisClass;
this.superClass = superClass;
@@ -254,11 +224,8 @@
return thisClass.stringValue();
}
- int getVersion() {
- return (majver << 16) + (char)minver;
- }
- String getVersionString() {
- return versionStringOf(majver, minver);
+ Version getVersion() {
+ return this.version;
}
// Note: equals and hashCode are identity-based.
@@ -1182,13 +1149,6 @@
}
}
- public static String versionStringOf(int majver, int minver) {
- return majver+"."+minver;
- }
- public static String versionStringOf(int version) {
- return versionStringOf(version >>> 16, (char)version);
- }
-
public void stripConstantFields() {
for (Class c : classes) {
for (Iterator<Class.Field> j = c.fields.iterator(); j.hasNext(); ) {
@@ -1342,4 +1302,75 @@
static final List<Class.Field> noFields = Arrays.asList(new Class.Field[0]);
static final List<Class.Method> noMethods = Arrays.asList(new Class.Method[0]);
static final List<InnerClass> noInnerClasses = Arrays.asList(new InnerClass[0]);
+
+ protected static final class Version {
+
+ public final short major;
+ public final short minor;
+
+ private Version(short major, short minor) {
+ this.major = major;
+ this.minor = minor;
+ }
+
+ public String toString() {
+ return major + "." + minor;
+ }
+
+ public boolean equals(Object that) {
+ return that instanceof Version
+ && major == ((Version)that).major
+ && minor == ((Version)that).minor;
+ }
+
+ public int intValue() {
+ return (major << 16) + minor;
+ }
+
+ public int hashCode() {
+ return (major << 16) + 7 + minor;
+ }
+
+ public static Version of(int major, int minor) {
+ return new Version((short)major, (short)minor);
+ }
+
+ public static Version of(byte[] bytes) {
+ int minor = ((bytes[0] & 0xFF) << 8) | (bytes[1] & 0xFF);
+ int major = ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF);
+ return new Version((short)major, (short)minor);
+ }
+
+ public static Version of(int major_minor) {
+ short minor = (short)major_minor;
+ short major = (short)(major_minor >>> 16);
+ return new Version(major, minor);
+ }
+
+ public static Version makeVersion(PropMap props, String partialKey) {
+ int min = props.getInteger(Utils.COM_PREFIX
+ + partialKey + ".minver", -1);
+ int maj = props.getInteger(Utils.COM_PREFIX
+ + partialKey + ".majver", -1);
+ return min >= 0 && maj >= 0 ? Version.of(maj, min) : null;
+ }
+ public byte[] asBytes() {
+ byte[] bytes = {
+ (byte) (minor >> 8), (byte) minor,
+ (byte) (major >> 8), (byte) major
+ };
+ return bytes;
+ }
+ public int compareTo(Version that) {
+ return this.intValue() - that.intValue();
+ }
+
+ public boolean lessThan(Version that) {
+ return compareTo(that) < 0 ;
+ }
+
+ public boolean greaterThan(Version that) {
+ return compareTo(that) > 0 ;
+ }
+ }
}
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java Tue May 29 13:16:17 2012 -0700
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java Tue May 29 14:56:48 2012 -0700
@@ -60,6 +60,7 @@
Package pkg;
byte[] bytes;
LimitedBuffer in;
+ Package.Version packageVersion;
PackageReader(Package pkg, InputStream in) throws IOException {
this.pkg = pkg;
@@ -220,7 +221,6 @@
final static int MAGIC_BYTES = 4;
void readArchiveMagic() throws IOException {
-
// Read a minimum of bytes in the first gulp.
in.setReadLimit(MAGIC_BYTES + AH_LENGTH_MIN);
@@ -230,10 +230,38 @@
archive_magic.readFrom(in);
// read and check magic numbers:
- pkg.magic = getMagicInt32();
+ int magic = getMagicInt32();
+ if (pkg.magic != magic) {
+ throw new IOException("Unexpected package magic number: got "
+ + magic + "; expected " + pkg.magic);
+ }
archive_magic.doneDisbursing();
}
+ // Fixed 6211177, converted to throw IOException
+ void checkArchiveVersion() throws IOException {
+ Package.Version versionFound = null;
+ for (Package.Version v : new Package.Version[] {
+ JAVA7_PACKAGE_VERSION,
+ JAVA6_PACKAGE_VERSION,
+ JAVA5_PACKAGE_VERSION
+ }) {
+ if (packageVersion.equals(v)) {
+ versionFound = v;
+ break;
+ }
+ }
+ if (versionFound == null) {
+ String expVer = JAVA7_PACKAGE_VERSION.toString()
+ + " OR "
+ + JAVA6_PACKAGE_VERSION.toString()
+ + " OR "
+ + JAVA5_PACKAGE_VERSION.toString();
+ throw new IOException("Unexpected package minor version: got "
+ + packageVersion.toString() + "; expected " + expVer);
+ }
+ }
+
void readArchiveHeader() throws IOException {
// archive_header:
// #archive_minver :UNSIGNED5[1]
@@ -264,10 +292,11 @@
archive_header_0.expectLength(AH_LENGTH_0);
archive_header_0.readFrom(in);
- pkg.package_minver = archive_header_0.getInt();
- pkg.package_majver = archive_header_0.getInt();
- pkg.checkVersion();
- this.initPackageMajver(pkg.package_majver);
+ int minver = archive_header_0.getInt();
+ int majver = archive_header_0.getInt();
+ packageVersion = Package.Version.of(majver, minver);
+ checkArchiveVersion();
+ this.initHighestClassVersion(JAVA7_MAX_CLASS_VERSION);
archiveOptions = archive_header_0.getInt();
archive_header_0.doneDisbursing();
@@ -324,8 +353,9 @@
numInnerClasses = archive_header_1.getInt();
- pkg.default_class_minver = (short) archive_header_1.getInt();
- pkg.default_class_majver = (short) archive_header_1.getInt();
+ minver = (short) archive_header_1.getInt();
+ majver = (short) archive_header_1.getInt();
+ pkg.defaultClassVersion = Package.Version.of(majver, minver);
numClasses = archive_header_1.getInt();
archive_header_1.doneDisbursing();
@@ -414,7 +444,7 @@
}
void checkLegacy(String bandname) {
- if (this.pkg.package_majver < JAVA7_PACKAGE_MAJOR_VERSION) {
+ if (packageVersion.lessThan(JAVA7_PACKAGE_VERSION)) {
throw new RuntimeException("unexpected band " + bandname);
}
}
@@ -947,9 +977,9 @@
name.stringValue(),
layout.stringValue());
// Check layout string for Java 6 extensions.
- String pvLayout = def.layoutForPackageMajver(getPackageMajver());
+ String pvLayout = def.layoutForClassVersion(getHighestClassVersion());
if (!pvLayout.equals(def.layout())) {
- throw new IOException("Bad attribute layout in version 150 archive: "+def.layout());
+ throw new IOException("Bad attribute layout in archive: "+def.layout());
}
this.setAttributeLayoutIndex(def, index);
if (dump != null) dump.println(index+" "+def);
@@ -1140,12 +1170,9 @@
Attribute retroVersion = cls.getAttribute(attrClassFileVersion);
if (retroVersion != null) {
cls.removeAttribute(retroVersion);
- short[] minmajver = parseClassFileVersionAttr(retroVersion);
- cls.minver = minmajver[0];
- cls.majver = minmajver[1];
+ cls.version = parseClassFileVersionAttr(retroVersion);
} else {
- cls.minver = pkg.default_class_minver;
- cls.majver = pkg.default_class_majver;
+ cls.version = pkg.defaultClassVersion;
}
// Replace null SourceFile by "obvious" string.
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java Tue May 29 13:16:17 2012 -0700
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java Tue May 29 14:56:48 2012 -0700
@@ -49,12 +49,13 @@
class PackageWriter extends BandStructure {
Package pkg;
OutputStream finalOut;
+ Package.Version packageVersion;
PackageWriter(Package pkg, OutputStream out) throws IOException {
this.pkg = pkg;
this.finalOut = out;
- // Caller has specified archive version in the package:
- initPackageMajver(pkg.package_majver);
+ // Caller has specified maximum class file version in the package:
+ initHighestClassVersion(pkg.getHighestClassVersion());
}
void write() throws IOException {
@@ -118,6 +119,57 @@
collectInnerClasses();
}
+ /*
+ * Convenience function to choose an archive version based
+ * on the class file versions observed within the archive
+ * or set the user defined version preset via properties.
+ */
+ void chooseDefaultPackageVersion() throws IOException {
+ if (pkg.packageVersion != null) {
+ packageVersion = pkg.packageVersion;
+ if (verbose > 0) {
+ Utils.log.info("package version overridden with: "
+ + packageVersion);
+ }
+ return;
+ }
+
+ Package.Version highV = getHighestClassVersion();
+ // set the package version now
+ if (highV.lessThan(JAVA6_MAX_CLASS_VERSION)) {
+ // There are only old classfiles in this segment or resources
+ packageVersion = JAVA5_PACKAGE_VERSION;
+ } else if (highV.equals(JAVA6_MAX_CLASS_VERSION) ||
+ (highV.equals(JAVA7_MAX_CLASS_VERSION) && !pkg.cp.haveExtraTags())) {
+ // force down the package version if we have jdk7 classes without
+ // any Indy references, this is because jdk7 class file (52.0) without
+ // Indy is identical to jdk6 class file (51.0).
+ packageVersion = JAVA6_PACKAGE_VERSION;
+ } else {
+ // Normal case. Use the newest archive format, when available
+ packageVersion = JAVA7_PACKAGE_VERSION;
+ }
+
+ if (verbose > 0) {
+ Utils.log.info("Highest version class file: " + highV
+ + " package version: " + packageVersion);
+ }
+ }
+
+ void checkVersion() throws IOException {
+ assert(packageVersion != null);
+
+ if (packageVersion.lessThan(JAVA7_PACKAGE_VERSION)) {
+ // this bit was reserved for future use in previous versions
+ if (testBit(archiveOptions, AO_HAVE_CP_EXTRAS)) {
+ throw new IOException("Format bits for Java 7 must be zero in previous releases");
+ }
+ }
+ if (testBit(archiveOptions, AO_UNUSED_MBZ)) {
+ throw new IOException("High archive option bits are reserved and must be zero: " + Integer.toHexString(archiveOptions));
+ }
+ }
+
void setArchiveOptions() {
// Decide on some archive options early.
// Does not decide on: AO_HAVE_SPECIAL_FORMATS,
@@ -168,11 +220,11 @@
}
}
// Decide on default version number (majority rule).
- Map<Integer, int[]> verCounts = new HashMap<>();
+ Map<Package.Version, int[]> verCounts = new HashMap<>();
int bestCount = 0;
- int bestVersion = -1;
+ Package.Version bestVersion = null;
for (Class cls : pkg.classes) {
- int version = cls.getVersion();
+ Package.Version version = cls.getVersion();
int[] var = verCounts.get(version);
if (var == null) {
var = new int[1];
@@ -186,28 +238,22 @@
}
}
verCounts.clear();
- if (bestVersion == -1) bestVersion = 0; // degenerate case
- int bestMajver = (char)(bestVersion >>> 16);
- int bestMinver = (char)(bestVersion);
- pkg.default_class_majver = (short) bestMajver;
- pkg.default_class_minver = (short) bestMinver;
- String bestVerStr = Package.versionStringOf(bestMajver, bestMinver);
+ if (bestVersion == null) bestVersion = JAVA_MIN_CLASS_VERSION; // degenerate case
+ pkg.defaultClassVersion = bestVersion;
if (verbose > 0)
- Utils.log.info("Consensus version number in segment is "+bestVerStr);
+ Utils.log.info("Consensus version number in segment is " + bestVersion);
if (verbose > 0)
- Utils.log.info("Highest version number in segment is "+
- Package.versionStringOf(pkg.getHighestClassVersion()));
+ Utils.log.info("Highest version number in segment is "
+ + pkg.getHighestClassVersion());
// Now add explicit pseudo-attrs. to classes with odd versions.
for (Class cls : pkg.classes) {
- if (cls.getVersion() != bestVersion) {
- Attribute a = makeClassFileVersionAttr(cls.minver, cls.majver);
+ if (!cls.getVersion().equals(bestVersion)) {
+ Attribute a = makeClassFileVersionAttr(cls.getVersion());
if (verbose > 1) {
- String clsVer = cls.getVersionString();
- String pkgVer = bestVerStr;
- Utils.log.fine("Version "+clsVer+" of "+cls
- +" doesn't match package version "
- +pkgVer);
+ Utils.log.fine("Version "+cls.getVersion() + " of " + cls
+ + " doesn't match package version "
+ + bestVersion);
}
// Note: Does not add in "natural" order. (Who cares?)
cls.addAttribute(a);
@@ -252,7 +298,7 @@
}
void writeFileHeader() throws IOException {
- pkg.checkVersion();
+ chooseDefaultPackageVersion();
writeArchiveMagic();
writeArchiveHeader();
}
@@ -322,12 +368,13 @@
if (haveCPExtra)
headerSizeForDebug += AH_CP_EXTRA_LEN;
- assert(pkg.package_majver > 0); // caller must specify!
- archive_header_0.putInt(pkg.package_minver);
- archive_header_0.putInt(pkg.package_majver);
+ // the archiveOptions are all initialized, sanity check now!.
+ checkVersion();
+
+ archive_header_0.putInt(packageVersion.minor);
+ archive_header_0.putInt(packageVersion.major);
if (verbose > 0)
- Utils.log.info("Package Version for this segment:"+
- Package.versionStringOf(pkg.getPackageVersion()));
+ Utils.log.info("Package Version for this segment:" + packageVersion);
archive_header_0.putInt(archiveOptions); // controls header format
assert(archive_header_0.length() == AH_LENGTH_0);
@@ -361,8 +408,8 @@
writeConstantPoolCounts(haveNumbers, haveCPExtra);
archive_header_1.putInt(pkg.getAllInnerClasses().size());
- archive_header_1.putInt(pkg.default_class_minver);
- archive_header_1.putInt(pkg.default_class_majver);
+ archive_header_1.putInt(pkg.defaultClassVersion.minor);
+ archive_header_1.putInt(pkg.defaultClassVersion.major);
archive_header_1.putInt(pkg.classes.size());
// Sanity: Make sure we came out to 29 (less optional fields):
@@ -892,7 +939,7 @@
if (predefIndex == null) {
// Make sure the package CP can name the local attribute.
Entry ne = ConstantPool.getUtf8Entry(def.name());
- String layout = def.layoutForPackageMajver(getPackageMajver());
+ String layout = def.layoutForClassVersion(getHighestClassVersion());
Entry le = ConstantPool.getUtf8Entry(layout);
requiredEntries.add(ne);
requiredEntries.add(le);
@@ -988,7 +1035,7 @@
assert((header & ADH_CONTEXT_MASK) == def.ctype());
attr_definition_headers.putByte(header);
attr_definition_name.putRef(ConstantPool.getUtf8Entry(def.name()));
- String layout = def.layoutForPackageMajver(getPackageMajver());
+ String layout = def.layoutForClassVersion(getHighestClassVersion());
attr_definition_layout.putRef(ConstantPool.getUtf8Entry(layout));
// Check that we are transmitting that correct attribute index:
boolean debug = false;
@@ -1542,8 +1589,8 @@
break;
default:
// CONSTANT_MethodHandle, etc.
- if (getPackageMajver() < JAVA7_PACKAGE_MAJOR_VERSION) {
- throw new IOException("bad package major version for Java 7 ldc");
+ if (getHighestClassVersion().lessThan(JAVA7_MAX_CLASS_VERSION)) {
+ throw new IOException("bad class file major version for Java 7 ldc");
}
bc_which = bc_loadablevalueref;
switch (bc) {
@@ -1581,8 +1628,8 @@
// Make sure the discarded bytes are sane:
assert(i.getConstant() == (1+((MemberEntry)ref).descRef.typeRef.computeSize(true)) << 8);
} else if (bc == _invokedynamic) {
- if (getPackageMajver() < JAVA7_PACKAGE_MAJOR_VERSION) {
- throw new IOException("bad package major version for Java 7 invokedynamic");
+ if (getHighestClassVersion().lessThan(JAVA7_MAX_CLASS_VERSION)) {
+ throw new IOException("bad class major version for Java 7 invokedynamic");
}
assert(i.getLength() == 5);
assert(i.getConstant() == 0); // last 2 bytes MBZ
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java Tue May 29 13:16:17 2012 -0700
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java Tue May 29 14:56:48 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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
@@ -164,8 +164,11 @@
if (verbose > 0) Utils.log.info(props.toString());
}
- // Here's where the bits are collected before getting packed:
- final Package pkg = new Package();
+ // Here's where the bits are collected before getting packed, we also
+ // initialize the version numbers now.
+ final Package pkg = new Package(Package.Version.makeVersion(props, "min.class"),
+ Package.Version.makeVersion(props, "max.class"),
+ Package.Version.makeVersion(props, "package"));
final String unknownAttrCommand;
{
@@ -280,23 +283,6 @@
}
{
- // Fill in permitted range of major/minor version numbers.
- int ver;
- if ((ver = props.getInteger(Utils.COM_PREFIX+"min.class.majver")) != 0)
- pkg.min_class_majver = (short) ver;
- if ((ver = props.getInteger(Utils.COM_PREFIX+"min.class.minver")) != 0)
- pkg.min_class_minver = (short) ver;
- if ((ver = props.getInteger(Utils.COM_PREFIX+"max.class.majver")) != 0)
- pkg.max_class_majver = (short) ver;
- if ((ver = props.getInteger(Utils.COM_PREFIX+"max.class.minver")) != 0)
- pkg.max_class_minver = (short) ver;
- if ((ver = props.getInteger(Utils.COM_PREFIX+"package.minver")) != 0)
- pkg.package_minver = (short) ver;
- if ((ver = props.getInteger(Utils.COM_PREFIX+"package.majver")) != 0)
- pkg.package_majver = (short) ver;
- }
-
- {
// Hook for testing: Forces use of special archive modes.
int opt = props.getInteger(Utils.COM_PREFIX+"archive.options");
if (opt != 0)
@@ -603,9 +589,6 @@
if (props.getBoolean(Utils.COM_PREFIX+"strip.exceptions")) pkg.stripAttributeKind("Exceptions");
if (props.getBoolean(Utils.COM_PREFIX+"strip.innerclasses")) pkg.stripAttributeKind("InnerClasses");
- // Must choose an archive version; PackageWriter does not.
- if (pkg.package_majver <= 0) pkg.choosePackageVersion();
-
PackageWriter pw = new PackageWriter(pkg, out);
pw.archiveNextCount = nextCount;
pw.write();
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java Tue May 29 13:16:17 2012 -0700
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java Tue May 29 14:56:48 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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
@@ -193,13 +193,18 @@
boolean setBoolean(String s, boolean val) {
return toBoolean(setProperty(s, String.valueOf(val)));
}
-
int toInteger(String val) {
- if (val == null) return 0;
+ return toInteger(val, 0);
+ }
+ int toInteger(String val, int def) {
+ if (val == null) return def;
if (Pack200.Packer.TRUE.equals(val)) return 1;
if (Pack200.Packer.FALSE.equals(val)) return 0;
return Integer.parseInt(val);
}
+ int getInteger(String s, int def) {
+ return toInteger(getProperty(s), def);
+ }
int getInteger(String s) {
return toInteger(getProperty(s));
}
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java Tue May 29 13:16:17 2012 -0700
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java Tue May 29 14:56:48 2012 -0700
@@ -25,12 +25,6 @@
package com.sun.java.util.jar.pack;
-import com.sun.java.util.jar.pack.ConstantPool.ClassEntry;
-import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry;
-import com.sun.java.util.jar.pack.ConstantPool.LiteralEntry;
-import com.sun.java.util.jar.pack.ConstantPool.MemberEntry;
-import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry;
-import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
@@ -38,9 +32,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.Collections;
import java.util.Date;
-import java.util.Enumeration;
-import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
@@ -211,9 +204,7 @@
static String getVersionString() {
return "Pack200, Vendor: " +
System.getProperty("java.vendor") +
- ", Version: " +
- Constants.JAVA6_PACKAGE_MAJOR_VERSION + "." +
- Constants.JAVA6_PACKAGE_MINOR_VERSION;
+ ", Version: " + Constants.MAX_PACKAGE_VERSION;
}
static void markJarFile(JarOutputStream out) throws IOException {
@@ -240,8 +231,7 @@
}
static void copyJarFile(JarFile in, JarOutputStream out) throws IOException {
byte[] buffer = new byte[1 << 14];
- for (Enumeration<JarEntry> e = in.entries(); e.hasMoreElements(); ) {
- JarEntry je = e.nextElement();
+ for (JarEntry je : Collections.list(in.entries())) {
out.putNextEntry(je);
InputStream ein = in.getInputStream(je);
for (int nr; 0 < (nr = ein.read(buffer)); ) {
--- a/jdk/test/tools/pack200/PackageVersionTest.java Tue May 29 13:16:17 2012 -0700
+++ b/jdk/test/tools/pack200/PackageVersionTest.java Tue May 29 14:56:48 2012 -0700
@@ -24,7 +24,7 @@
/*
* @test
- * @bug 6712743 6991164
+ * @bug 6712743 6991164 7168401
* @summary verify package versions
* @compile -XDignore.symbol.file Utils.java PackageVersionTest.java
* @run main PackageVersionTest
@@ -71,8 +71,9 @@
verifyPack("Test6.class", JAVA6_PACKAGE_MAJOR_VERSION,
JAVA6_PACKAGE_MINOR_VERSION);
- verifyPack("Test7.class", JAVA7_PACKAGE_MAJOR_VERSION,
- JAVA7_PACKAGE_MINOR_VERSION);
+ // a jar file devoid of indy classes must generate 160.1 package file
+ 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,
@@ -84,7 +85,7 @@
String versionStr = unpacker.toString();
String expected = "Pack200, Vendor: " +
System.getProperty("java.vendor") + ", Version: " +
- JAVA6_PACKAGE_MAJOR_VERSION + "." + JAVA6_PACKAGE_MINOR_VERSION;
+ JAVA7_PACKAGE_MAJOR_VERSION + "." + JAVA7_PACKAGE_MINOR_VERSION;
if (!versionStr.equals(expected)) {
System.out.println("Expected: " + expected);
System.out.println("Obtained: " + versionStr);