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