提交 3e2b261e 编写于 作者: K ksrini

7168401: pack200 does not produce a compatible pack file for JDK7 classes if indy is not present

Reviewed-by: jrose
上级 4b2c2953
...@@ -653,8 +653,8 @@ class Attribute implements Comparable<Attribute> { ...@@ -653,8 +653,8 @@ class Attribute implements Comparable<Attribute> {
return fixups[0]; // return ref-bearing cookie, if any return fixups[0]; // return ref-bearing cookie, if any
} }
public String layoutForPackageMajver(int majver) { public String layoutForClassVersion(Package.Version vers) {
if (majver <= JAVA5_PACKAGE_MAJOR_VERSION) { if (vers.lessThan(JAVA6_MAX_CLASS_VERSION)) {
// Disallow layout syntax in the oldest protocol version. // Disallow layout syntax in the oldest protocol version.
return expandCaseDashNotation(layout); return expandCaseDashNotation(layout);
} }
......
...@@ -74,30 +74,27 @@ class BandStructure { ...@@ -74,30 +74,27 @@ class BandStructure {
abstract protected Index getCPIndex(byte tag); abstract protected Index getCPIndex(byte tag);
// Local copy of package version. // Local copy of highest class version.
private int packageMajver = -1; private Package.Version highestClassVersion = null;
/** Call this exactly once, early, to specify the archive major version. */ /** Call this exactly once, early, to specify the archive major version. */
public void initPackageMajver(int packageMajver) throws IOException { public void initHighestClassVersion(Package.Version highestClassVersion) throws IOException {
assert(packageMajver > 0 && packageMajver < 0x10000); if (this.highestClassVersion != null) {
if (this.packageMajver > 0) {
throw new IOException( throw new IOException(
"Package majver is already initialized to " + this.packageMajver+ "Highest class major version is already initialized to " +
"; new setting is " + packageMajver); this.highestClassVersion + "; new setting is " + highestClassVersion);
} }
this.packageMajver = packageMajver; this.highestClassVersion = highestClassVersion;
adjustToMajver(); adjustToClassVersion();
} }
public int getPackageMajver() {
if (packageMajver < 0) { public Package.Version getHighestClassVersion() {
throw new RuntimeException("Package majver not yet initialized"); return highestClassVersion;
}
return packageMajver;
} }
private final boolean isReader = this instanceof PackageReader; private final boolean isReader = this instanceof PackageReader;
protected BandStructure() {
} protected BandStructure() {}
final static Coding BYTE1 = Coding.of(1,256); final static Coding BYTE1 = Coding.of(1,256);
...@@ -1866,20 +1863,12 @@ class BandStructure { ...@@ -1866,20 +1863,12 @@ class BandStructure {
attrClassFileVersionMask = (1<<CLASS_ATTR_ClassFile_version); attrClassFileVersionMask = (1<<CLASS_ATTR_ClassFile_version);
} }
private void adjustToMajver() throws IOException { private void adjustToClassVersion() throws IOException {
if (getPackageMajver() < JAVA6_PACKAGE_MAJOR_VERSION) { if (getHighestClassVersion().lessThan(JAVA6_MAX_CLASS_VERSION)) {
if (verbose > 0) Utils.log.fine("Legacy package version"); if (verbose > 0) Utils.log.fine("Legacy package version");
// Revoke definition of pre-1.6 attribute type. // Revoke definition of pre-1.6 attribute type.
undefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE); 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() { protected void initAttrIndexLimit() {
...@@ -1942,21 +1931,14 @@ class BandStructure { ...@@ -1942,21 +1931,14 @@ class BandStructure {
} }
} }
protected Attribute makeClassFileVersionAttr(int minver, int majver) { protected Attribute makeClassFileVersionAttr(Package.Version ver) {
byte[] bytes = { return attrClassFileVersion.addContent(ver.asBytes());
(byte)(minver >> 8), (byte)minver,
(byte)(majver >> 8), (byte)majver
};
return attrClassFileVersion.addContent(bytes);
} }
protected short[] parseClassFileVersionAttr(Attribute attr) { protected Package.Version parseClassFileVersionAttr(Attribute attr) {
assert(attr.layout() == attrClassFileVersion); assert(attr.layout() == attrClassFileVersion);
assert(attr.size() == 4); assert(attr.size() == 4);
byte[] bytes = attr.bytes(); return Package.Version.of(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 };
} }
private boolean assertBandOKForElems(Band[] ab, Attribute.Layout.Element[] elems) { private boolean assertBandOKForElems(Band[] ab, Attribute.Layout.Element[] elems) {
......
...@@ -174,27 +174,31 @@ class ClassReader { ...@@ -174,27 +174,31 @@ class ClassReader {
("Bad magic number in class file " ("Bad magic number in class file "
+Integer.toHexString(cls.magic), +Integer.toHexString(cls.magic),
ATTR_CONTEXT_CLASS, "magic-number", "pass"); ATTR_CONTEXT_CLASS, "magic-number", "pass");
cls.minver = (short) readUnsignedShort(); int minver = (short) readUnsignedShort();
cls.majver = (short) readUnsignedShort(); int majver = (short) readUnsignedShort();
cls.version = Package.Version.of(majver, minver);
//System.out.println("ClassFile.version="+cls.majver+"."+cls.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) { if (bad != null) {
throw new Attribute.FormatException throw new Attribute.FormatException
("classfile version too "+bad+": " ("classfile version too "+bad+": "
+cls.majver+"."+cls.minver+" in "+cls.file, +cls.version+" in "+cls.file,
ATTR_CONTEXT_CLASS, "version", "pass"); ATTR_CONTEXT_CLASS, "version", "pass");
} }
} }
private String checkVersion(int majver, int minver) { private String checkVersion(Package.Version ver) {
if (majver < pkg.min_class_majver || int majver = ver.major;
(majver == pkg.min_class_majver && int minver = ver.minor;
minver < pkg.min_class_minver)) { if (majver < pkg.minClassVersion.major ||
(majver == pkg.minClassVersion.major &&
minver < pkg.minClassVersion.minor)) {
return "small"; return "small";
} }
if (majver > pkg.max_class_majver || if (majver > pkg.maxClassVersion.major ||
(majver == pkg.max_class_majver && (majver == pkg.maxClassVersion.major &&
minver > pkg.max_class_minver)) { minver > pkg.maxClassVersion.minor)) {
return "large"; return "large";
} }
return null; // OK return null; // OK
......
...@@ -113,8 +113,8 @@ class ClassWriter { ...@@ -113,8 +113,8 @@ class ClassWriter {
void writeMagicNumbers() throws IOException { void writeMagicNumbers() throws IOException {
writeInt(cls.magic); writeInt(cls.magic);
writeShort(cls.minver); writeShort(cls.version.minor);
writeShort(cls.majver); writeShort(cls.version.major);
} }
void writeConstantPool() throws IOException { void writeConstantPool() throws IOException {
......
...@@ -43,30 +43,40 @@ class Constants { ...@@ -43,30 +43,40 @@ class Constants {
1.0 to 1.3.X 45,3 1.0 to 1.3.X 45,3
1.4 to 1.4.X 46,0 1.4 to 1.4.X 46,0
1.5 to 1.5.X 49,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 Package.Version JAVA_MIN_CLASS_VERSION =
public final static short JAVA_MIN_CLASS_MINOR_VERSION = 03; Package.Version.of(45, 03);
public final static short JAVA5_MAX_CLASS_MAJOR_VERSION = 49; public final static Package.Version JAVA5_MAX_CLASS_VERSION =
public final static short JAVA5_MAX_CLASS_MINOR_VERSION = 0; Package.Version.of(49, 00);
public final static short JAVA6_MAX_CLASS_MAJOR_VERSION = 50; public final static Package.Version JAVA6_MAX_CLASS_VERSION =
public final static short JAVA6_MAX_CLASS_MINOR_VERSION = 0; Package.Version.of(50, 00);
public final static short JAVA7_MAX_CLASS_MAJOR_VERSION = 51; public final static Package.Version JAVA7_MAX_CLASS_VERSION =
public final static short JAVA7_MAX_CLASS_MINOR_VERSION = 0; Package.Version.of(51, 00);
public final static int JAVA_PACKAGE_MAGIC = 0xCAFED00D; 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 int JAVA6_PACKAGE_MAJOR_VERSION = 160; public final static Package.Version JAVA5_PACKAGE_VERSION =
public final static int JAVA6_PACKAGE_MINOR_VERSION = 1; Package.Version.of(150, 7);
public final static int JAVA7_PACKAGE_MAJOR_VERSION = 170; public final static Package.Version JAVA6_PACKAGE_VERSION =
public final static int JAVA7_PACKAGE_MINOR_VERSION = 1; Package.Version.of(160, 1);
public final static Package.Version JAVA7_PACKAGE_VERSION =
Package.Version.of(170, 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_INDEX_LIMIT = 0x10000;
public final static int CONSTANT_POOL_NARROW_LIMIT = 0x00100; public final static int CONSTANT_POOL_NARROW_LIMIT = 0x00100;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
package com.sun.java.util.jar.pack; 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.Attribute.Layout;
import com.sun.java.util.jar.pack.ConstantPool.ClassEntry; 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.DescriptorEntry;
...@@ -67,46 +68,58 @@ class Package { ...@@ -67,46 +68,58 @@ class Package {
verbose = pmap.getInteger(Utils.DEBUG_VERBOSE); verbose = pmap.getInteger(Utils.DEBUG_VERBOSE);
} }
int magic; final int magic = JAVA_PACKAGE_MAGIC;
int package_minver;
int package_majver;
int default_modtime = NO_MODTIME; int default_modtime = NO_MODTIME;
int default_options = 0; // FO_DEFLATE_HINT int default_options = 0; // FO_DEFLATE_HINT
short default_class_majver = -1; // fill in later Version defaultClassVersion = null;
short default_class_minver = 0; // fill in later
// These fields can be adjusted by driver properties. // These fields can be adjusted by driver properties.
short min_class_majver = JAVA_MIN_CLASS_MAJOR_VERSION; final Version minClassVersion;
short min_class_minver = JAVA_MIN_CLASS_MINOR_VERSION; final Version maxClassVersion;
short max_class_majver = JAVA7_MAX_CLASS_MAJOR_VERSION; // null, indicates that consensus rules during package write
short max_class_minver = JAVA7_MAX_CLASS_MINOR_VERSION; final Version packageVersion;
Version observedHighestClassVersion = null;
short observed_max_class_majver = min_class_majver;
short observed_max_class_minver = min_class_minver;
// What constants are used in this unit? // What constants are used in this unit?
ConstantPool.IndexGroup cp = new ConstantPool.IndexGroup(); ConstantPool.IndexGroup cp = new ConstantPool.IndexGroup();
Package() { /*
magic = JAVA_PACKAGE_MAGIC; * typically used by the PackageReader to set the defaults, in which
package_minver = -1; // fill in later * case we take the defaults.
package_majver = 0; // fill in later */
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(); cp = new ConstantPool.IndexGroup();
classes.clear(); classes.clear();
files.clear(); files.clear();
BandStructure.nextSeqForDebug = 0; BandStructure.nextSeqForDebug = 0;
package_minver = -1; // fill in later observedHighestClassVersion = null;
package_majver = 0; // fill in later
}
int getPackageVersion() {
return (package_majver << 16) + package_minver;
} }
// Special empty versions of Code and InnerClasses, used for markers. // Special empty versions of Code and InnerClasses, used for markers.
...@@ -128,73 +141,31 @@ class Package { ...@@ -128,73 +141,31 @@ class Package {
attrDefs = Collections.unmodifiableMap(ad); attrDefs = Collections.unmodifiableMap(ad);
} }
int getDefaultClassVersion() { Version getDefaultClassVersion() {
return (default_class_majver << 16) + (char)default_class_minver; return defaultClassVersion;
} }
/** Return the highest version number of all classes, /** Return the highest version number of all classes,
* or 0 if there are no classes. * or 0 if there are no classes.
*/ */
int getHighestClassVersion() { private void setHighestClassVersion() {
int res = 0; // initial low value if (observedHighestClassVersion != null)
return;
Version res = JAVA_MIN_CLASS_VERSION; // initial low value
for (Class cls : classes) { for (Class cls : classes) {
int ver = cls.getVersion(); Version ver = cls.getVersion();
if (res < ver) res = ver; if (res.lessThan(ver)) res = ver;
} }
return res; observedHighestClassVersion = res;
} }
/** Convenience function to choose an archive version based Version getHighestClassVersion() {
* on the class file versions observed within the archive. setHighestClassVersion();
*/ return observedHighestClassVersion;
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;
}
} }
// What Java classes are in this unit? // 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<>(); ArrayList<Package.Class> classes = new ArrayList<>();
public List<Package.Class> getClasses() { public List<Package.Class> getClasses() {
...@@ -210,7 +181,7 @@ class Package { ...@@ -210,7 +181,7 @@ class Package {
// File header // File header
int magic; int magic;
short minver, majver; Version version;
// Local constant pool (one-way mapping of index => package cp). // Local constant pool (one-way mapping of index => package cp).
Entry[] cpMap; Entry[] cpMap;
...@@ -231,8 +202,7 @@ class Package { ...@@ -231,8 +202,7 @@ class Package {
Class(int flags, ClassEntry thisClass, ClassEntry superClass, ClassEntry[] interfaces) { Class(int flags, ClassEntry thisClass, ClassEntry superClass, ClassEntry[] interfaces) {
this.magic = JAVA_MAGIC; this.magic = JAVA_MAGIC;
this.minver = default_class_minver; this.version = defaultClassVersion;
this.majver = default_class_majver;
this.flags = flags; this.flags = flags;
this.thisClass = thisClass; this.thisClass = thisClass;
this.superClass = superClass; this.superClass = superClass;
...@@ -254,11 +224,8 @@ class Package { ...@@ -254,11 +224,8 @@ class Package {
return thisClass.stringValue(); return thisClass.stringValue();
} }
int getVersion() { Version getVersion() {
return (majver << 16) + (char)minver; return this.version;
}
String getVersionString() {
return versionStringOf(majver, minver);
} }
// Note: equals and hashCode are identity-based. // Note: equals and hashCode are identity-based.
...@@ -1182,13 +1149,6 @@ class Package { ...@@ -1182,13 +1149,6 @@ class Package {
} }
} }
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() { public void stripConstantFields() {
for (Class c : classes) { for (Class c : classes) {
for (Iterator<Class.Field> j = c.fields.iterator(); j.hasNext(); ) { for (Iterator<Class.Field> j = c.fields.iterator(); j.hasNext(); ) {
...@@ -1342,4 +1302,75 @@ class Package { ...@@ -1342,4 +1302,75 @@ class Package {
static final List<Class.Field> noFields = Arrays.asList(new Class.Field[0]); 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<Class.Method> noMethods = Arrays.asList(new Class.Method[0]);
static final List<InnerClass> noInnerClasses = Arrays.asList(new InnerClass[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 ;
}
}
} }
...@@ -60,6 +60,7 @@ class PackageReader extends BandStructure { ...@@ -60,6 +60,7 @@ class PackageReader extends BandStructure {
Package pkg; Package pkg;
byte[] bytes; byte[] bytes;
LimitedBuffer in; LimitedBuffer in;
Package.Version packageVersion;
PackageReader(Package pkg, InputStream in) throws IOException { PackageReader(Package pkg, InputStream in) throws IOException {
this.pkg = pkg; this.pkg = pkg;
...@@ -220,7 +221,6 @@ class PackageReader extends BandStructure { ...@@ -220,7 +221,6 @@ class PackageReader extends BandStructure {
final static int MAGIC_BYTES = 4; final static int MAGIC_BYTES = 4;
void readArchiveMagic() throws IOException { void readArchiveMagic() throws IOException {
// Read a minimum of bytes in the first gulp. // Read a minimum of bytes in the first gulp.
in.setReadLimit(MAGIC_BYTES + AH_LENGTH_MIN); in.setReadLimit(MAGIC_BYTES + AH_LENGTH_MIN);
...@@ -230,10 +230,38 @@ class PackageReader extends BandStructure { ...@@ -230,10 +230,38 @@ class PackageReader extends BandStructure {
archive_magic.readFrom(in); archive_magic.readFrom(in);
// read and check magic numbers: // 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(); 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 { void readArchiveHeader() throws IOException {
// archive_header: // archive_header:
// #archive_minver :UNSIGNED5[1] // #archive_minver :UNSIGNED5[1]
...@@ -264,10 +292,11 @@ class PackageReader extends BandStructure { ...@@ -264,10 +292,11 @@ class PackageReader extends BandStructure {
archive_header_0.expectLength(AH_LENGTH_0); archive_header_0.expectLength(AH_LENGTH_0);
archive_header_0.readFrom(in); archive_header_0.readFrom(in);
pkg.package_minver = archive_header_0.getInt(); int minver = archive_header_0.getInt();
pkg.package_majver = archive_header_0.getInt(); int majver = archive_header_0.getInt();
pkg.checkVersion(); packageVersion = Package.Version.of(majver, minver);
this.initPackageMajver(pkg.package_majver); checkArchiveVersion();
this.initHighestClassVersion(JAVA7_MAX_CLASS_VERSION);
archiveOptions = archive_header_0.getInt(); archiveOptions = archive_header_0.getInt();
archive_header_0.doneDisbursing(); archive_header_0.doneDisbursing();
...@@ -324,8 +353,9 @@ class PackageReader extends BandStructure { ...@@ -324,8 +353,9 @@ class PackageReader extends BandStructure {
numInnerClasses = archive_header_1.getInt(); numInnerClasses = archive_header_1.getInt();
pkg.default_class_minver = (short) archive_header_1.getInt(); minver = (short) archive_header_1.getInt();
pkg.default_class_majver = (short) archive_header_1.getInt(); majver = (short) archive_header_1.getInt();
pkg.defaultClassVersion = Package.Version.of(majver, minver);
numClasses = archive_header_1.getInt(); numClasses = archive_header_1.getInt();
archive_header_1.doneDisbursing(); archive_header_1.doneDisbursing();
...@@ -414,7 +444,7 @@ class PackageReader extends BandStructure { ...@@ -414,7 +444,7 @@ class PackageReader extends BandStructure {
} }
void checkLegacy(String bandname) { 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); throw new RuntimeException("unexpected band " + bandname);
} }
} }
...@@ -947,9 +977,9 @@ class PackageReader extends BandStructure { ...@@ -947,9 +977,9 @@ class PackageReader extends BandStructure {
name.stringValue(), name.stringValue(),
layout.stringValue()); layout.stringValue());
// Check layout string for Java 6 extensions. // Check layout string for Java 6 extensions.
String pvLayout = def.layoutForPackageMajver(getPackageMajver()); String pvLayout = def.layoutForClassVersion(getHighestClassVersion());
if (!pvLayout.equals(def.layout())) { 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); this.setAttributeLayoutIndex(def, index);
if (dump != null) dump.println(index+" "+def); if (dump != null) dump.println(index+" "+def);
...@@ -1140,12 +1170,9 @@ class PackageReader extends BandStructure { ...@@ -1140,12 +1170,9 @@ class PackageReader extends BandStructure {
Attribute retroVersion = cls.getAttribute(attrClassFileVersion); Attribute retroVersion = cls.getAttribute(attrClassFileVersion);
if (retroVersion != null) { if (retroVersion != null) {
cls.removeAttribute(retroVersion); cls.removeAttribute(retroVersion);
short[] minmajver = parseClassFileVersionAttr(retroVersion); cls.version = parseClassFileVersionAttr(retroVersion);
cls.minver = minmajver[0];
cls.majver = minmajver[1];
} else { } else {
cls.minver = pkg.default_class_minver; cls.version = pkg.defaultClassVersion;
cls.majver = pkg.default_class_majver;
} }
// Replace null SourceFile by "obvious" string. // Replace null SourceFile by "obvious" string.
......
...@@ -49,12 +49,13 @@ import static com.sun.java.util.jar.pack.Constants.*; ...@@ -49,12 +49,13 @@ import static com.sun.java.util.jar.pack.Constants.*;
class PackageWriter extends BandStructure { class PackageWriter extends BandStructure {
Package pkg; Package pkg;
OutputStream finalOut; OutputStream finalOut;
Package.Version packageVersion;
PackageWriter(Package pkg, OutputStream out) throws IOException { PackageWriter(Package pkg, OutputStream out) throws IOException {
this.pkg = pkg; this.pkg = pkg;
this.finalOut = out; this.finalOut = out;
// Caller has specified archive version in the package: // Caller has specified maximum class file version in the package:
initPackageMajver(pkg.package_majver); initHighestClassVersion(pkg.getHighestClassVersion());
} }
void write() throws IOException { void write() throws IOException {
...@@ -118,6 +119,57 @@ class PackageWriter extends BandStructure { ...@@ -118,6 +119,57 @@ class PackageWriter extends BandStructure {
collectInnerClasses(); 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() { void setArchiveOptions() {
// Decide on some archive options early. // Decide on some archive options early.
// Does not decide on: AO_HAVE_SPECIAL_FORMATS, // Does not decide on: AO_HAVE_SPECIAL_FORMATS,
...@@ -168,11 +220,11 @@ class PackageWriter extends BandStructure { ...@@ -168,11 +220,11 @@ class PackageWriter extends BandStructure {
} }
} }
// Decide on default version number (majority rule). // Decide on default version number (majority rule).
Map<Integer, int[]> verCounts = new HashMap<>(); Map<Package.Version, int[]> verCounts = new HashMap<>();
int bestCount = 0; int bestCount = 0;
int bestVersion = -1; Package.Version bestVersion = null;
for (Class cls : pkg.classes) { for (Class cls : pkg.classes) {
int version = cls.getVersion(); Package.Version version = cls.getVersion();
int[] var = verCounts.get(version); int[] var = verCounts.get(version);
if (var == null) { if (var == null) {
var = new int[1]; var = new int[1];
...@@ -186,28 +238,22 @@ class PackageWriter extends BandStructure { ...@@ -186,28 +238,22 @@ class PackageWriter extends BandStructure {
} }
} }
verCounts.clear(); verCounts.clear();
if (bestVersion == -1) bestVersion = 0; // degenerate case if (bestVersion == null) bestVersion = JAVA_MIN_CLASS_VERSION; // degenerate case
int bestMajver = (char)(bestVersion >>> 16); pkg.defaultClassVersion = bestVersion;
int bestMinver = (char)(bestVersion);
pkg.default_class_majver = (short) bestMajver;
pkg.default_class_minver = (short) bestMinver;
String bestVerStr = Package.versionStringOf(bestMajver, bestMinver);
if (verbose > 0) 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) if (verbose > 0)
Utils.log.info("Highest version number in segment is "+ Utils.log.info("Highest version number in segment is "
Package.versionStringOf(pkg.getHighestClassVersion())); + pkg.getHighestClassVersion());
// Now add explicit pseudo-attrs. to classes with odd versions. // Now add explicit pseudo-attrs. to classes with odd versions.
for (Class cls : pkg.classes) { for (Class cls : pkg.classes) {
if (cls.getVersion() != bestVersion) { if (!cls.getVersion().equals(bestVersion)) {
Attribute a = makeClassFileVersionAttr(cls.minver, cls.majver); Attribute a = makeClassFileVersionAttr(cls.getVersion());
if (verbose > 1) { if (verbose > 1) {
String clsVer = cls.getVersionString(); Utils.log.fine("Version "+cls.getVersion() + " of " + cls
String pkgVer = bestVerStr; + " doesn't match package version "
Utils.log.fine("Version "+clsVer+" of "+cls + bestVersion);
+" doesn't match package version "
+pkgVer);
} }
// Note: Does not add in "natural" order. (Who cares?) // Note: Does not add in "natural" order. (Who cares?)
cls.addAttribute(a); cls.addAttribute(a);
...@@ -252,7 +298,7 @@ class PackageWriter extends BandStructure { ...@@ -252,7 +298,7 @@ class PackageWriter extends BandStructure {
} }
void writeFileHeader() throws IOException { void writeFileHeader() throws IOException {
pkg.checkVersion(); chooseDefaultPackageVersion();
writeArchiveMagic(); writeArchiveMagic();
writeArchiveHeader(); writeArchiveHeader();
} }
...@@ -322,12 +368,13 @@ class PackageWriter extends BandStructure { ...@@ -322,12 +368,13 @@ class PackageWriter extends BandStructure {
if (haveCPExtra) if (haveCPExtra)
headerSizeForDebug += AH_CP_EXTRA_LEN; headerSizeForDebug += AH_CP_EXTRA_LEN;
assert(pkg.package_majver > 0); // caller must specify! // the archiveOptions are all initialized, sanity check now!.
archive_header_0.putInt(pkg.package_minver); checkVersion();
archive_header_0.putInt(pkg.package_majver);
archive_header_0.putInt(packageVersion.minor);
archive_header_0.putInt(packageVersion.major);
if (verbose > 0) if (verbose > 0)
Utils.log.info("Package Version for this segment:"+ Utils.log.info("Package Version for this segment:" + packageVersion);
Package.versionStringOf(pkg.getPackageVersion()));
archive_header_0.putInt(archiveOptions); // controls header format archive_header_0.putInt(archiveOptions); // controls header format
assert(archive_header_0.length() == AH_LENGTH_0); assert(archive_header_0.length() == AH_LENGTH_0);
...@@ -361,8 +408,8 @@ class PackageWriter extends BandStructure { ...@@ -361,8 +408,8 @@ class PackageWriter extends BandStructure {
writeConstantPoolCounts(haveNumbers, haveCPExtra); writeConstantPoolCounts(haveNumbers, haveCPExtra);
archive_header_1.putInt(pkg.getAllInnerClasses().size()); archive_header_1.putInt(pkg.getAllInnerClasses().size());
archive_header_1.putInt(pkg.default_class_minver); archive_header_1.putInt(pkg.defaultClassVersion.minor);
archive_header_1.putInt(pkg.default_class_majver); archive_header_1.putInt(pkg.defaultClassVersion.major);
archive_header_1.putInt(pkg.classes.size()); archive_header_1.putInt(pkg.classes.size());
// Sanity: Make sure we came out to 29 (less optional fields): // Sanity: Make sure we came out to 29 (less optional fields):
...@@ -892,7 +939,7 @@ class PackageWriter extends BandStructure { ...@@ -892,7 +939,7 @@ class PackageWriter extends BandStructure {
if (predefIndex == null) { if (predefIndex == null) {
// Make sure the package CP can name the local attribute. // Make sure the package CP can name the local attribute.
Entry ne = ConstantPool.getUtf8Entry(def.name()); Entry ne = ConstantPool.getUtf8Entry(def.name());
String layout = def.layoutForPackageMajver(getPackageMajver()); String layout = def.layoutForClassVersion(getHighestClassVersion());
Entry le = ConstantPool.getUtf8Entry(layout); Entry le = ConstantPool.getUtf8Entry(layout);
requiredEntries.add(ne); requiredEntries.add(ne);
requiredEntries.add(le); requiredEntries.add(le);
...@@ -988,7 +1035,7 @@ class PackageWriter extends BandStructure { ...@@ -988,7 +1035,7 @@ class PackageWriter extends BandStructure {
assert((header & ADH_CONTEXT_MASK) == def.ctype()); assert((header & ADH_CONTEXT_MASK) == def.ctype());
attr_definition_headers.putByte(header); attr_definition_headers.putByte(header);
attr_definition_name.putRef(ConstantPool.getUtf8Entry(def.name())); 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)); attr_definition_layout.putRef(ConstantPool.getUtf8Entry(layout));
// Check that we are transmitting that correct attribute index: // Check that we are transmitting that correct attribute index:
boolean debug = false; boolean debug = false;
...@@ -1542,8 +1589,8 @@ class PackageWriter extends BandStructure { ...@@ -1542,8 +1589,8 @@ class PackageWriter extends BandStructure {
break; break;
default: default:
// CONSTANT_MethodHandle, etc. // CONSTANT_MethodHandle, etc.
if (getPackageMajver() < JAVA7_PACKAGE_MAJOR_VERSION) { if (getHighestClassVersion().lessThan(JAVA7_MAX_CLASS_VERSION)) {
throw new IOException("bad package major version for Java 7 ldc"); throw new IOException("bad class file major version for Java 7 ldc");
} }
bc_which = bc_loadablevalueref; bc_which = bc_loadablevalueref;
switch (bc) { switch (bc) {
...@@ -1581,8 +1628,8 @@ class PackageWriter extends BandStructure { ...@@ -1581,8 +1628,8 @@ class PackageWriter extends BandStructure {
// Make sure the discarded bytes are sane: // Make sure the discarded bytes are sane:
assert(i.getConstant() == (1+((MemberEntry)ref).descRef.typeRef.computeSize(true)) << 8); assert(i.getConstant() == (1+((MemberEntry)ref).descRef.typeRef.computeSize(true)) << 8);
} else if (bc == _invokedynamic) { } else if (bc == _invokedynamic) {
if (getPackageMajver() < JAVA7_PACKAGE_MAJOR_VERSION) { if (getHighestClassVersion().lessThan(JAVA7_MAX_CLASS_VERSION)) {
throw new IOException("bad package major version for Java 7 invokedynamic"); throw new IOException("bad class major version for Java 7 invokedynamic");
} }
assert(i.getLength() == 5); assert(i.getLength() == 5);
assert(i.getConstant() == 0); // last 2 bytes MBZ assert(i.getConstant() == 0); // last 2 bytes MBZ
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -164,8 +164,11 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { ...@@ -164,8 +164,11 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
if (verbose > 0) Utils.log.info(props.toString()); if (verbose > 0) Utils.log.info(props.toString());
} }
// Here's where the bits are collected before getting packed: // Here's where the bits are collected before getting packed, we also
final Package pkg = new Package(); // 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; final String unknownAttrCommand;
{ {
...@@ -279,23 +282,6 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { ...@@ -279,23 +282,6 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
if (verbose > 0) Utils.log.info("passFiles = " + passFiles); if (verbose > 0) Utils.log.info("passFiles = " + passFiles);
} }
{
// 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. // Hook for testing: Forces use of special archive modes.
int opt = props.getInteger(Utils.COM_PREFIX+"archive.options"); int opt = props.getInteger(Utils.COM_PREFIX+"archive.options");
...@@ -603,9 +589,6 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { ...@@ -603,9 +589,6 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
if (props.getBoolean(Utils.COM_PREFIX+"strip.exceptions")) pkg.stripAttributeKind("Exceptions"); if (props.getBoolean(Utils.COM_PREFIX+"strip.exceptions")) pkg.stripAttributeKind("Exceptions");
if (props.getBoolean(Utils.COM_PREFIX+"strip.innerclasses")) pkg.stripAttributeKind("InnerClasses"); 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); PackageWriter pw = new PackageWriter(pkg, out);
pw.archiveNextCount = nextCount; pw.archiveNextCount = nextCount;
pw.write(); pw.write();
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -193,13 +193,18 @@ final class PropMap implements SortedMap<String, String> { ...@@ -193,13 +193,18 @@ final class PropMap implements SortedMap<String, String> {
boolean setBoolean(String s, boolean val) { boolean setBoolean(String s, boolean val) {
return toBoolean(setProperty(s, String.valueOf(val))); return toBoolean(setProperty(s, String.valueOf(val)));
} }
int toInteger(String 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.TRUE.equals(val)) return 1;
if (Pack200.Packer.FALSE.equals(val)) return 0; if (Pack200.Packer.FALSE.equals(val)) return 0;
return Integer.parseInt(val); return Integer.parseInt(val);
} }
int getInteger(String s, int def) {
return toInteger(getProperty(s), def);
}
int getInteger(String s) { int getInteger(String s) {
return toInteger(getProperty(s)); return toInteger(getProperty(s));
} }
......
...@@ -25,12 +25,6 @@ ...@@ -25,12 +25,6 @@
package com.sun.java.util.jar.pack; 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.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.File; import java.io.File;
...@@ -38,9 +32,8 @@ import java.io.FilterOutputStream; ...@@ -38,9 +32,8 @@ import java.io.FilterOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.Enumeration;
import java.util.Map;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.jar.JarInputStream; import java.util.jar.JarInputStream;
...@@ -211,9 +204,7 @@ class Utils { ...@@ -211,9 +204,7 @@ class Utils {
static String getVersionString() { static String getVersionString() {
return "Pack200, Vendor: " + return "Pack200, Vendor: " +
System.getProperty("java.vendor") + System.getProperty("java.vendor") +
", Version: " + ", Version: " + Constants.MAX_PACKAGE_VERSION;
Constants.JAVA6_PACKAGE_MAJOR_VERSION + "." +
Constants.JAVA6_PACKAGE_MINOR_VERSION;
} }
static void markJarFile(JarOutputStream out) throws IOException { static void markJarFile(JarOutputStream out) throws IOException {
...@@ -240,8 +231,7 @@ class Utils { ...@@ -240,8 +231,7 @@ class Utils {
} }
static void copyJarFile(JarFile in, JarOutputStream out) throws IOException { static void copyJarFile(JarFile in, JarOutputStream out) throws IOException {
byte[] buffer = new byte[1 << 14]; byte[] buffer = new byte[1 << 14];
for (Enumeration<JarEntry> e = in.entries(); e.hasMoreElements(); ) { for (JarEntry je : Collections.list(in.entries())) {
JarEntry je = e.nextElement();
out.putNextEntry(je); out.putNextEntry(je);
InputStream ein = in.getInputStream(je); InputStream ein = in.getInputStream(je);
for (int nr; 0 < (nr = ein.read(buffer)); ) { for (int nr; 0 < (nr = ein.read(buffer)); ) {
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
/* /*
* @test * @test
* @bug 6712743 6991164 * @bug 6712743 6991164 7168401
* @summary verify package versions * @summary verify package versions
* @compile -XDignore.symbol.file Utils.java PackageVersionTest.java * @compile -XDignore.symbol.file Utils.java PackageVersionTest.java
* @run main PackageVersionTest * @run main PackageVersionTest
...@@ -71,8 +71,9 @@ public class PackageVersionTest { ...@@ -71,8 +71,9 @@ public class PackageVersionTest {
verifyPack("Test6.class", JAVA6_PACKAGE_MAJOR_VERSION, verifyPack("Test6.class", JAVA6_PACKAGE_MAJOR_VERSION,
JAVA6_PACKAGE_MINOR_VERSION); JAVA6_PACKAGE_MINOR_VERSION);
verifyPack("Test7.class", JAVA7_PACKAGE_MAJOR_VERSION, // a jar file devoid of indy classes must generate 160.1 package file
JAVA7_PACKAGE_MINOR_VERSION); verifyPack("Test7.class", JAVA6_PACKAGE_MAJOR_VERSION,
JAVA6_PACKAGE_MINOR_VERSION);
// test for resource file, ie. no class files // test for resource file, ie. no class files
verifyPack("Test6.java", JAVA5_PACKAGE_MAJOR_VERSION, verifyPack("Test6.java", JAVA5_PACKAGE_MAJOR_VERSION,
...@@ -84,7 +85,7 @@ public class PackageVersionTest { ...@@ -84,7 +85,7 @@ public class PackageVersionTest {
String versionStr = unpacker.toString(); String versionStr = unpacker.toString();
String expected = "Pack200, Vendor: " + String expected = "Pack200, Vendor: " +
System.getProperty("java.vendor") + ", Version: " + 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)) { if (!versionStr.equals(expected)) {
System.out.println("Expected: " + expected); System.out.println("Expected: " + expected);
System.out.println("Obtained: " + versionStr); System.out.println("Obtained: " + versionStr);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册