# HG changeset patch # User ksrini # Date 1287092468 25200 # Node ID a3ca6758633338782c31c9b9b0e3ee01b0e11050 # Parent 1584742c6abf71fd76c25d010a51c39ac19571a9 6982312: (pack200) pack200 fails with the jdk7 class files Reviewed-by: jrose diff -r 1584742c6abf -r a3ca67586333 jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java Fri Oct 15 10:59:03 2010 -0400 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java Thu Oct 14 14:41:08 2010 -0700 @@ -246,7 +246,9 @@ fixups[fptr++] = in.readUnsignedShort(); break; default: - throw new IOException("Bad constant pool tag "+tag); + throw new ClassFormatException("Bad constant pool tag " + + tag + " in File: " + cls.file.nameString + + " at pos: " + inPos); } } @@ -415,7 +417,12 @@ if (a.name() == "Code") { Class.Method m = (Class.Method) h; m.code = new Code(m); - readCode(m.code); + try { + readCode(m.code); + } catch (Instruction.FormatException iie) { + String message = iie.getMessage() + " in " + h; + throw new ClassReader.ClassFormatException(message); + } } else { assert(h == cls); readInnerClasses(cls); @@ -438,6 +445,7 @@ code.max_locals = readUnsignedShort(); code.bytes = new byte[readInt()]; in.readFully(code.bytes); + Instruction.opcodeChecker(code.bytes); int nh = readUnsignedShort(); code.setHandlerCount(nh); for (int i = 0; i < nh; i++) { @@ -463,4 +471,10 @@ cls.innerClasses = ics; // set directly; do not use setInnerClasses. // (Later, ics may be transferred to the pkg.) } + + class ClassFormatException extends IOException { + public ClassFormatException(String message) { + super(message); + } + } } diff -r 1584742c6abf -r a3ca67586333 jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java Fri Oct 15 10:59:03 2010 -0400 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java Thu Oct 14 14:41:08 2010 -0700 @@ -25,6 +25,8 @@ package com.sun.java.util.jar.pack; +import java.io.IOException; + /** * A parsed bytecode instruction. * Provides accessors to various relevant bits. @@ -628,4 +630,21 @@ } } } + + public static void opcodeChecker(byte[] code) throws FormatException { + Instruction i = at(code, 0); + while (i != null) { + int opcode = i.getBC(); + if (opcode == _xxxunusedxxx || opcode < _nop || opcode > _jsr_w) { + String message = "illegal opcode: " + opcode + " " + i; + throw new FormatException(message); + } + i = i.next(); + } + } + static class FormatException extends IOException { + FormatException(String message) { + super(message); + } + } } diff -r 1584742c6abf -r a3ca67586333 jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java Fri Oct 15 10:59:03 2010 -0400 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java Thu Oct 14 14:41:08 2010 -0700 @@ -496,15 +496,29 @@ reader.unknownAttrCommand = unknownAttrCommand; try { reader.read(); - } catch (Attribute.FormatException ee) { - // He passed up the category to us in layout. - if (ee.layout.equals(Pack200.Packer.PASS)) { - Utils.log.warning("Passing class file uncompressed due to unrecognized attribute: "+fname); - Utils.log.info(ee.toString()); - return null; + } catch (IOException ioe) { + String message = "Passing class file uncompressed due to"; + if (ioe instanceof Attribute.FormatException) { + Attribute.FormatException ee = (Attribute.FormatException) ioe; + // He passed up the category to us in layout. + if (ee.layout.equals(Pack200.Packer.PASS)) { + Utils.log.info(ee.toString()); + Utils.log.warning(message + " unrecognized attribute: " + + fname); + return null; + } + } else if (ioe instanceof ClassReader.ClassFormatException) { + ClassReader.ClassFormatException ce = (ClassReader.ClassFormatException) ioe; + // %% TODO: Do we invent a new property for this or reuse %% + if (unknownAttrCommand.equals(Pack200.Packer.PASS)) { + Utils.log.info(ce.toString()); + Utils.log.warning(message + " unknown class format: " + + fname); + return null; + } } // Otherwise, it must be an error. - throw ee; + throw ioe; } pkg.addClass(cls); return cls.file; diff -r 1584742c6abf -r a3ca67586333 jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java Fri Oct 15 10:59:03 2010 -0400 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java Thu Oct 14 14:41:08 2010 -0700 @@ -182,11 +182,8 @@ } public void warning(String msg, Object param) { - int verbose = currentPropMap().getInteger(DEBUG_VERBOSE); - if (verbose > 0) { getLogger().warning(msg, param); } - } public void warning(String msg) { warning(msg, null); diff -r 1584742c6abf -r a3ca67586333 jdk/test/tools/pack200/AttributeTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/tools/pack200/AttributeTests.java Thu Oct 14 14:41:08 2010 -0700 @@ -0,0 +1,75 @@ +/* + * 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. + */ + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/* + * @test + * @bug 6982312 + * @summary tests various classfile format and attribute handling by pack200 + * @compile -XDignore.symbol.file Utils.java AttributeTests.java + * @run main AttributeTests + * @author ksrini + */ + + +public class AttributeTests { + + public static void main(String... args) throws Exception { + test6982312(); + } + /* + * This is an interim test, which ensures pack200 handles JSR-292 related + * classfile changes seamlessly, until all the classfile changes in jdk7 + * and jdk8 are fully supported. At that time this test should be jettisoned, + * along with the associated jar file. + * + * The jar file contains sources and classes noting the classes were + * derived by using the javac from the lambda project, + * see http://openjdk.java.net/projects/lambda/. + * Therefore the classes contained in the jar cannot be compiled, using + * the standard jdk7's javac compiler. + */ + static void test6982312() throws IOException { + String pack200Cmd = Utils.getPack200Cmd(); + File dynJar = new File(".", "dyn.jar"); + Utils.copyFile(new File(Utils.TEST_SRC_DIR, "dyn.jar"), dynJar); + File testJar = new File(".", "test.jar"); + List<String> cmds = new ArrayList<String>(); + cmds.add(pack200Cmd); + cmds.add("--repack"); + cmds.add(testJar.getAbsolutePath()); + cmds.add(dynJar.getAbsolutePath()); + Utils.runExec(cmds); + /* + * compare the repacked jar bit-wise, as all the files + * should be transmitted "as-is". + */ + Utils.doCompareBitWise(dynJar.getAbsoluteFile(), testJar.getAbsoluteFile()); + testJar.delete(); + dynJar.delete(); + } +} diff -r 1584742c6abf -r a3ca67586333 jdk/test/tools/pack200/dyn.jar Binary file jdk/test/tools/pack200/dyn.jar has changed