1/* 2 * Copyright (c) 2011, 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 * @test 26 * @bug 6836682 7025988 27 * @summary JavacFileManager handling of zip64 archives (Scenario A and B) 28 * @modules jdk.compiler 29 * jdk.jartool/sun.tools.jar 30 * @compile -XDignore.symbol.file T6836682.java Utils.java 31 * @run main T6836682 32 */ 33/* 34 * This test consists of two scenarios: 35 * 36 * Scenario A: create a jar with entries exceeding 64K, and see if the javac 37 * can handle this large jar on the classpath. Generally this test completes 38 * within a minute 39 * 40 * Scenario B: create a jar with a large enough file exceeding 4GB, and 41 * similarly test javac. This test is known to be slow and problematic on 42 * certain operating systems, thus this test can be selected by passing a 43 * property through jtreg as follows: 44 * -javaoptions=-DT6836682.testScenarioB=true. 45 * Note this test will only run iff all the disk requirements are met at runtime. 46 */ 47import java.io.BufferedInputStream; 48import java.io.BufferedOutputStream; 49import java.io.File; 50import java.io.FileInputStream; 51import java.io.FileOutputStream; 52import java.io.IOException; 53import java.io.OutputStream; 54import java.nio.file.Files; 55import java.nio.file.Path; 56import java.util.zip.CRC32; 57import java.util.zip.ZipEntry; 58import java.util.zip.ZipOutputStream; 59 60public class T6836682 { 61 62 private static final long GIGA = 1024 * 1024 * 1024; 63 private static final int BUFFER_LEN = Short.MAX_VALUE * 2; 64 65 static long getCount(long minlength) { 66 return (minlength / BUFFER_LEN) + 1; 67 } 68 69 static long computeCRC(long minlength) { 70 CRC32 crc = new CRC32(); 71 byte[] buffer = new byte[BUFFER_LEN]; 72 long count = getCount(minlength); 73 for (long i = 0; i < count; i++) { 74 crc.update(buffer); 75 } 76 return crc.getValue(); 77 } 78 79 static long computeCRC(File inFile) throws IOException { 80 byte[] buffer = new byte[8192]; 81 CRC32 crc = new CRC32(); 82 FileInputStream fis = null; 83 BufferedInputStream bis = null; 84 try { 85 fis = new FileInputStream(inFile); 86 bis = new BufferedInputStream(fis); 87 int n = bis.read(buffer); 88 while (n > 0) { 89 crc.update(buffer, 0, n); 90 n = bis.read(buffer); 91 } 92 } finally { 93 Utils.close(bis); 94 Utils.close(fis); 95 } 96 return crc.getValue(); 97 } 98 99 static void createLargeFile(OutputStream os, long minlength) throws IOException { 100 byte[] buffer = new byte[BUFFER_LEN]; 101 long count = getCount(minlength); 102 for (long i = 0; i < count; i++) { 103 os.write(buffer); 104 } 105 os.flush(); 106 } 107 108 static void createJarWithLargeFile(File jarFile, File javaFile, 109 long minlength) throws IOException { 110 Utils.createClassFile(javaFile, null, true); 111 File classFile = new File(Utils.getClassFileName(javaFile)); 112 ZipOutputStream zos = null; 113 BufferedOutputStream bos = null; 114 FileInputStream fis = null; 115 try { 116 zos = new ZipOutputStream(new FileOutputStream(jarFile)); 117 zos.setLevel(ZipOutputStream.STORED); 118 zos.setMethod(0); 119 bos = new BufferedOutputStream(zos); 120 121 ZipEntry ze = new ZipEntry("large.data"); 122 ze.setCompressedSize(getCount(minlength) * BUFFER_LEN); 123 ze.setSize(getCount(minlength) * BUFFER_LEN); 124 ze.setCrc(computeCRC(minlength)); 125 ze.setMethod(ZipEntry.STORED); 126 zos.putNextEntry(ze); 127 createLargeFile(bos, minlength); 128 129 ze = new ZipEntry(classFile.getName()); 130 ze.setCompressedSize(classFile.length()); 131 ze.setSize(classFile.length()); 132 ze.setCrc(computeCRC(classFile)); 133 ze.setMethod(ZipEntry.STORED); 134 zos.putNextEntry(ze); 135 fis = new FileInputStream(classFile); 136 Utils.copyStream(fis, bos); 137 bos.flush(); 138 zos.closeEntry(); 139 } finally { 140 Utils.close(bos); 141 Utils.close(zos); 142 Utils.close(fis); 143 } 144 // deleted to prevent accidental linkage 145 new File(Utils.getClassFileName(javaFile)).delete(); 146 } 147 148 static void createLargeJar(File jarFile, File javaFile) throws IOException { 149 File classFile = new File(Utils.getClassFileName(javaFile)); 150 Utils.createClassFile(javaFile, null, true); 151 ZipOutputStream zos = null; 152 FileInputStream fis = null; 153 final int MAX = Short.MAX_VALUE * 2 + 10; 154 ZipEntry ze = null; 155 try { 156 zos = new ZipOutputStream(new FileOutputStream(jarFile)); 157 zos.setLevel(ZipOutputStream.STORED); 158 zos.setMethod(ZipOutputStream.STORED); 159 for (int i = 0; i < MAX ; i++) { 160 ze = new ZipEntry("X" + i + ".txt"); 161 ze.setSize(0); 162 ze.setCompressedSize(0); 163 ze.setCrc(0); 164 zos.putNextEntry(ze); 165 } 166 167 // add a class file 168 ze = new ZipEntry(classFile.getName()); 169 ze.setCompressedSize(classFile.length()); 170 ze.setSize(classFile.length()); 171 ze.setCrc(computeCRC(classFile)); 172 zos.putNextEntry(ze); 173 fis = new FileInputStream(classFile); 174 Utils.copyStream(fis, zos); 175 } finally { 176 Utils.close(zos); 177 Utils.close(fis); 178 // deleted to prevent accidental linkage 179 new File(Utils.getClassFileName(javaFile)).delete(); 180 } 181 } 182 183 // a jar with entries exceeding 64k + a class file for the existential test 184 public static void testScenarioA(String... args) throws IOException { 185 File largeJar = new File("large.jar"); 186 File javaFile = new File("Foo.java"); 187 createLargeJar(largeJar, javaFile); 188 189 File testFile = new File("Bar.java"); 190 try { 191 Utils.createJavaFile(testFile, javaFile); 192 if (!Utils.compile("-doe", "-verbose", "-cp", 193 largeJar.getAbsolutePath(), testFile.getAbsolutePath())) { 194 throw new IOException("test failed"); 195 } 196 } finally { 197 Utils.deleteFile(largeJar); 198 } 199 } 200 201 // a jar with an enormous file + a class file for the existential test 202 public static void testScenarioB(String... args) throws IOException { 203 final File largeJar = new File("huge.jar"); 204 final File javaFile = new File("Foo.java"); 205 206 final Path path = largeJar.getAbsoluteFile().getParentFile().toPath(); 207 final long available = Files.getFileStore(path).getUsableSpace(); 208 final long MAX_VALUE = 0xFFFF_FFFFL; 209 210 final long absolute = MAX_VALUE + 1L; 211 final long required = (long)(absolute * 1.1); // pad for sundries 212 System.out.println("\tavailable: " + available / GIGA + " GB"); 213 System.out.println("\trequired: " + required / GIGA + " GB"); 214 215 if (available > required) { 216 createJarWithLargeFile(largeJar, javaFile, absolute); 217 File testFile = new File("Bar.java"); 218 Utils.createJavaFile(testFile, javaFile); 219 try { 220 if (!Utils.compile("-doe", "-verbose", "-cp", 221 largeJar.getAbsolutePath(), testFile.getAbsolutePath())) { 222 throw new IOException("test failed"); 223 } 224 } finally { 225 Utils.deleteFile(largeJar); 226 } 227 } else { 228 System.out.println("Warning: testScenarioB passes vacuously," + 229 " requirements exceeds available space"); 230 } 231 } 232 233 public static void main(String... args) throws IOException { 234 testScenarioA(); 235 System.out.println("testScenarioA: PASS"); 236 if (Boolean.getBoolean("T6836682.testScenarioB")) { 237 testScenarioB(); 238 System.out.println("testScenarioB: PASS"); 239 } else { 240 System.out.println("Warning: testScenarioB, large file test skipped"); 241 } 242 } 243} 244