LoadClassFromJava6CreatedJarTest.java revision 3170:dc017a37aac5
1/*
2 * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24
25/*
26 * @test
27 * @bug 8003512
28 * @summary javac doesn't work with jar files with >64k entries
29 * @modules jdk.compiler
30 *          jdk.jartool/sun.tools.jar
31 * @compile -target 6 -source 6 -XDignore.symbol.file LoadClassFromJava6CreatedJarTest.java ../Utils.java
32 * @run main/timeout=360 LoadClassFromJava6CreatedJarTest
33 */
34
35/*
36 * The test creates a jar file with more than 64K entries. The jar file is
37 * created executing the LoadClassFromJava6CreatedJarTest$MakeJar
38 * class with a JVM version 6. The test must include Java 6 features only.
39 *
40 * The aim is to verify classes included in jar files with more than 64K entries
41 * created with Java 6 can be loaded by more recent versions of Java.
42 *
43 * A path to JDK or JRE version 6 is needed. This can be provided
44 * by passing this option to jtreg:
45 * -javaoption:-Djava6.home="/path/to/jdk_or_jre6"
46 */
47
48import java.io.BufferedInputStream;
49import java.io.BufferedReader;
50import java.io.File;
51import java.io.FileInputStream;
52import java.io.FileOutputStream;
53import java.io.IOException;
54import java.io.InputStreamReader;
55import java.util.Arrays;
56import java.util.List;
57import java.util.zip.CRC32;
58import java.util.zip.ZipEntry;
59import java.util.zip.ZipOutputStream;
60
61public class LoadClassFromJava6CreatedJarTest {
62
63    static final String javaHome6 = System.getProperty("java6.home");
64    static final String testClasses = System.getProperty("test.classes");
65
66    public static void main(String... args)
67            throws IOException, InterruptedException {
68        if (javaHome6 != null) {
69            new LoadClassFromJava6CreatedJarTest().run();
70        } else {
71            System.out.println(
72                "The test LoadClassFromJava6CreatedJarTest cannot be executed. " +
73                "In order to run it you should pass an option with " +
74                "this form -javaoption:-Djava6.home=\"/path/to/jdk_or_jre6\" " +
75                "to jtreg.");
76        }
77    }
78
79    void run() throws IOException, InterruptedException {
80        File classA = new File("A.java");
81        Utils.createJavaFile(classA, null);
82        if (!Utils.compile("-target", "6", "-source", "6",
83            classA.getAbsolutePath())) {
84            throw new AssertionError("Test failed while compiling class A");
85        }
86
87        executeCommand(Arrays.asList(javaHome6 + "/bin/java", "-classpath",
88            testClasses, "LoadClassFromJava6CreatedJarTest$MakeJar"));
89
90        File classB = new File("B.java");
91        Utils.createJavaFile(classB, classA);
92        if (!Utils.compile("-cp", "a.jar", classB.getAbsolutePath())) {
93            throw new AssertionError("Test failed while compiling class Main");
94        }
95    }
96
97    void executeCommand(List<String> command)
98            throws IOException, InterruptedException {
99        ProcessBuilder pb = new ProcessBuilder(command).
100            redirectErrorStream(true);
101        Process p = pb.start();
102        BufferedReader r =
103            new BufferedReader(new InputStreamReader(p.getInputStream()));
104        String line;
105        while ((line = r.readLine()) != null) {
106            System.err.println(line);
107        }
108        int rc = p.waitFor();
109        if (rc != 0) {
110            throw new AssertionError("Unexpected exit code: " + rc);
111        }
112    }
113
114    static class MakeJar {
115        public static void main(String[] args) throws Throwable {
116            File classFile = new File("A.class");
117            ZipOutputStream zos = null;
118            FileInputStream fis = null;
119            final int MAX = Short.MAX_VALUE * 2 + 10;
120            ZipEntry ze = null;
121            try {
122                zos = new ZipOutputStream(new FileOutputStream("a.jar"));
123                zos.setLevel(ZipOutputStream.STORED);
124                zos.setMethod(ZipOutputStream.STORED);
125                for (int i = 0; i < MAX ; i++) {
126                    ze = new ZipEntry("X" + i + ".txt");
127                    ze.setSize(0);
128                    ze.setCompressedSize(0);
129                    ze.setCrc(0);
130                    zos.putNextEntry(ze);
131                }
132
133                // add a class file
134                ze = new ZipEntry("A.class");
135                ze.setCompressedSize(classFile.length());
136                ze.setSize(classFile.length());
137                ze.setCrc(computeCRC(classFile));
138                zos.putNextEntry(ze);
139                fis = new FileInputStream(classFile);
140                for (int c; (c = fis.read()) >= 0;) {
141                    zos.write(c);
142                }
143            } finally {
144                zos.close();
145                fis.close();
146            }
147        }
148
149        private static final int BUFFER_LEN = Short.MAX_VALUE * 2;
150
151        static long getCount(long minlength) {
152            return (minlength / BUFFER_LEN) + 1;
153        }
154
155        static long computeCRC(long minlength) {
156            CRC32 crc = new CRC32();
157            byte[] buffer = new byte[BUFFER_LEN];
158            long count = getCount(minlength);
159            for (long i = 0; i < count; i++) {
160                crc.update(buffer);
161            }
162            return crc.getValue();
163        }
164
165        static long computeCRC(File inFile) throws IOException {
166            byte[] buffer = new byte[8192];
167            CRC32 crc = new CRC32();
168            FileInputStream fis = null;
169            BufferedInputStream bis = null;
170            try {
171                fis = new FileInputStream(inFile);
172                bis = new BufferedInputStream(fis);
173                int n = bis.read(buffer);
174                while (n > 0) {
175                    crc.update(buffer, 0, n);
176                    n = bis.read(buffer);
177                }
178            } finally {
179                bis.close();
180                fis.close();
181            }
182            return crc.getValue();
183        }
184    }
185}
186