< prev index next >

test/hotspot/jtreg/runtime/appcds/SharedArchiveConsistency.java

Print this page




  44 import java.io.FileOutputStream;
  45 import java.io.IOException;
  46 import java.nio.ByteBuffer;
  47 import java.nio.ByteOrder;
  48 import java.nio.channels.FileChannel;
  49 import java.nio.file.Files;
  50 import java.nio.file.Path;
  51 import java.nio.file.Paths;
  52 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
  53 import java.nio.file.StandardOpenOption;
  54 import static java.nio.file.StandardOpenOption.READ;
  55 import static java.nio.file.StandardOpenOption.WRITE;
  56 import java.util.ArrayList;
  57 import java.util.HashSet;
  58 import java.util.List;
  59 import java.util.Random;
  60 import sun.hotspot.WhiteBox;
  61 
  62 public class SharedArchiveConsistency {
  63     public static WhiteBox wb;
  64     public static int offset_magic;    // FileMapHeader::_magic


  65     public static int sp_offset_crc;   // CDSFileMapRegion::_crc

  66     public static int file_header_size = -1;// total size of header, variant, need calculation
  67     public static int CDSFileMapRegion_size; // size of CDSFileMapRegion
  68     public static int sp_offset;       // offset of CDSFileMapRegion
  69     public static int sp_used_offset;  // offset of CDSFileMapRegion::_used
  70     public static int size_t_size;     // size of size_t

  71 
  72     public static File jsa;        // will be updated during test
  73     public static File orgJsaFile; // kept the original file not touched.
  74     // The following should be consistent with the enum in the C++ MetaspaceShared class
  75     public static String[] shared_region_name = {
  76         "mc",          // MiscCode
  77         "rw",          // ReadWrite
  78         "ro",          // ReadOnly
  79         "md",          // MiscData
  80         "first_closed_archive",
  81         "last_closed_archive",
  82         "first_open_archive",
  83         "last_open_archive"
  84     };
  85 
  86     public static int num_regions = shared_region_name.length;
  87     public static String[] matchMessages = {
  88         "Unable to use shared archive",
  89         "An error has occurred while processing the shared archive file.",
  90         "Checksum verification failed.",
  91         "The shared archive file has been truncated."
  92     };
  93 
  94     public static void getFileOffsetInfo() throws Exception {
  95         wb = WhiteBox.getWhiteBox();
  96         offset_magic = wb.getOffsetForName("FileMapHeader::_magic");


  97         sp_offset_crc = wb.getOffsetForName("CDSFileMapRegion::_crc");
  98         try {
  99             int nonExistOffset = wb.getOffsetForName("FileMapHeader::_non_exist_offset");
 100             System.exit(-1); // should fail
 101         } catch (Exception e) {
 102             // success
 103         }
 104 
 105         sp_offset = wb.getOffsetForName("FileMapHeader::_space[0]") - offset_magic;
 106         sp_used_offset = wb.getOffsetForName("CDSFileMapRegion::_used") - sp_offset_crc;
 107         size_t_size = wb.getOffsetForName("size_t_size");
 108         CDSFileMapRegion_size  = wb.getOffsetForName("CDSFileMapRegion_size");
 109     }
 110 
 111     public static int getFileHeaderSize(FileChannel fc) throws Exception {
 112         if (file_header_size != -1) {
 113             return file_header_size;
 114         }
 115         // this is not real header size, it is struct size
 116         int int_size = wb.getOffsetForName("int_size");
 117         file_header_size = wb.getOffsetForName("file_header_size");
 118         int offset_path_misc_info = wb.getOffsetForName("FileMapHeader::_paths_misc_info_size") -
 119             offset_magic;
 120         int path_misc_info_size   = (int)readInt(fc, offset_path_misc_info, int_size);
 121         file_header_size += path_misc_info_size; //readInt(fc, offset_path_misc_info, size_t_size);
 122         System.out.println("offset_path_misc_info = " + offset_path_misc_info);
 123         System.out.println("path_misc_info_size   = " + path_misc_info_size);
 124         System.out.println("file_header_size      = " + file_header_size);
 125         file_header_size = (int)align_up_page(file_header_size);
 126         System.out.println("file_header_size (aligned to page) = " + file_header_size);
 127         return file_header_size;
 128     }
 129 
 130     public static long align_up_page(long l) throws Exception {
 131         // wb is obtained in getFileOffsetInfo() which is called first in main() else we should call
 132         // WhiteBox.getWhiteBox() here first.
 133         int pageSize = wb.getVMPageSize();
 134         return (l + pageSize -1) & (~ (pageSize - 1));
 135     }
 136 
 137     private static long getRandomBetween(long start, long end) throws Exception {
 138         if (start > end) {
 139             throw new IllegalArgumentException("start must be less than end");
 140         }
 141         Random aRandom = Utils.getRandomInstance();
 142         int d = aRandom.nextInt((int)(end - start));
 143         if (d < 1) {
 144             d = 1;
 145         }
 146         return start + d;
 147     }
 148 
 149     public static long readInt(FileChannel fc, long offset, int nbytes) throws Exception {
 150         ByteBuffer bb = ByteBuffer.allocate(nbytes);
 151         bb.order(ByteOrder.nativeOrder());
 152         fc.position(offset);
 153         fc.read(bb);
 154         return  (nbytes > 4 ? bb.getLong(0) : bb.getInt(0));
 155     }
 156 
 157     public static void writeData(FileChannel fc, long offset, ByteBuffer bb) throws Exception {
 158         fc.position(offset);
 159         fc.write(bb);
 160         fc.force(true);
 161     }
 162 
 163     public static FileChannel getFileChannel() throws Exception {
 164         List<StandardOpenOption> arry = new ArrayList<StandardOpenOption>();
 165         arry.add(READ);
 166         arry.add(WRITE);
 167         return FileChannel.open(jsa.toPath(), new HashSet<StandardOpenOption>(arry));
 168     }
 169 
 170     public static void modifyJsaContentRandomly() throws Exception {
 171         FileChannel fc = getFileChannel();
 172         // corrupt random area in the data areas
 173         long[] used    = new long[num_regions];       // record used bytes
 174         long start0, start, end, off;
 175         int used_offset, path_info_size;
 176 
 177         int bufSize;
 178         System.out.printf("%-24s%12s%12s%16s\n", "Space Name", "Used bytes", "Reg Start", "Random Offset");
 179         start0 = getFileHeaderSize(fc);
 180         for (int i = 0; i < num_regions; i++) {
 181             used[i] = get_region_used_size_aligned(fc, i);
 182             start = start0;
 183             for (int j = 0; j < i; j++) {
 184                 start += align_up_page(used[j]);
 185             }
 186             end = start + used[i];
 187             if (start == end) {
 188                 continue; // Ignore empty regions
 189             }
 190             off = getRandomBetween(start, end);
 191             System.out.printf("%-24s%12d%12d%16d\n", shared_region_name[i], used[i], start, off);


 193                 bufSize = (int)(end - off + 1);
 194             } else {
 195                 bufSize = 1024;
 196             }
 197             ByteBuffer bbuf = ByteBuffer.wrap(new byte[bufSize]);
 198             writeData(fc, off, bbuf);
 199         }
 200         if (fc.isOpen()) {
 201             fc.close();
 202         }
 203     }
 204 
 205     static long get_region_used_size_aligned(FileChannel fc, int region) throws Exception {
 206         long n = sp_offset + CDSFileMapRegion_size * region + sp_used_offset;
 207         long alignment = WhiteBox.getWhiteBox().metaspaceReserveAlignment();
 208         long used = readInt(fc, n, size_t_size);
 209         used = (used + alignment - 1) & ~(alignment - 1);
 210         return used;
 211     }
 212 
 213     public static boolean modifyJsaContent(int region) throws Exception {
 214         FileChannel fc = getFileChannel();
 215         byte[] buf = new byte[4096];
 216         ByteBuffer bbuf = ByteBuffer.wrap(buf);
 217 
 218         long total = 0L;
 219         long[] used = new long[num_regions];
 220         System.out.printf("%-24s%12s\n", "Space name", "Used bytes");
 221         for (int i = 0; i < num_regions; i++) {
 222             used[i] = get_region_used_size_aligned(fc, i);
 223             System.out.printf("%-24s%12d\n", shared_region_name[i], used[i]);
 224             total += used[i];
 225         }
 226         System.out.printf("%-24s%12d\n", "Total: ", total);
 227         long header_size = getFileHeaderSize(fc);
 228         long region_start_offset = header_size;
 229         for (int i=0; i<region; i++) {
 230             region_start_offset += used[i];
 231         }
 232         if (used[region] == 0) {
 233             System.out.println("Region " + shared_region_name[region] + " is empty. Nothing to corrupt.");
 234             return false;
 235         }
 236         System.out.println("Corrupt " + shared_region_name[region] + " section, start = " + region_start_offset
 237                            + " (header_size + 0x" + Long.toHexString(region_start_offset-header_size) + ")");
 238         long bytes_written = 0L;
 239         while (bytes_written < used[region]) {
 240             writeData(fc, region_start_offset + bytes_written, bbuf);
 241             bbuf.clear();
 242             bytes_written += 4096;
 243         }
 244         fc.force(true);
 245         if (fc.isOpen()) {
 246             fc.close();
 247         }
 248         return true;
 249     }
 250 
 251     public static void modifyJsaHeader() throws Exception {
 252         FileChannel fc = getFileChannel();
 253         // screw up header info
 254         byte[] buf = new byte[getFileHeaderSize(fc)];
 255         ByteBuffer bbuf = ByteBuffer.wrap(buf);
 256         writeData(fc, 0L, bbuf);
 257         if (fc.isOpen()) {
 258             fc.close();
 259         }
 260     }
 261 
























 262     public static void copyFile(File from, File to) throws Exception {
 263         if (to.exists()) {
 264             if(!to.delete()) {
 265                 throw new IOException("Could not delete file " + to);
 266             }
 267         }
 268         to.createNewFile();
 269         setReadWritePermission(to);
 270         Files.copy(from.toPath(), to.toPath(), REPLACE_EXISTING);
 271     }
 272 
 273     // Copy file with bytes deleted or inserted
 274     // del -- true, deleted, false, inserted
 275     public static void copyFile(File from, File to, boolean del) throws Exception {
 276         try (
 277             FileChannel inputChannel = new FileInputStream(from).getChannel();
 278             FileChannel outputChannel = new FileOutputStream(to).getChannel()
 279         ) {
 280             long size = inputChannel.size();
 281             int init_size = getFileHeaderSize(inputChannel);


 331     //   3) keep header correct but modify content in each region specified by shared_region_name[]
 332     //   4) update both header and content, test
 333     //   5) delete bytes in data begining
 334     //   6) insert bytes in data begining
 335     //   7) randomly corrupt data in each region specified by shared_region_name[]
 336     public static void main(String... args) throws Exception {
 337         // must call to get offset info first!!!
 338         getFileOffsetInfo();
 339         Path currentRelativePath = Paths.get("");
 340         String currentDir = currentRelativePath.toAbsolutePath().toString();
 341         System.out.println("Current relative path is: " + currentDir);
 342         // get jar file
 343         String jarFile = JarBuilder.getOrCreateHelloJar();
 344 
 345         // dump (appcds.jsa created)
 346         TestCommon.testDump(jarFile, null);
 347 
 348         // test, should pass
 349         System.out.println("1. Normal, should pass but may fail\n");
 350 
 351         String[] execArgs = {"-cp", jarFile, "Hello"};
 352         // tests that corrupt contents of the archive need to run with
 353         // VerifySharedSpaces enabled to detect inconsistencies
 354         String[] verifyExecArgs = {"-XX:+VerifySharedSpaces", "-cp", jarFile, "Hello"};
 355 
 356         OutputAnalyzer output = TestCommon.execCommon(execArgs);
 357 
 358         try {
 359             TestCommon.checkExecReturn(output, 0, true, "Hello World");
 360         } catch (Exception e) {
 361             TestCommon.checkExecReturn(output, 1, true, matchMessages[0]);
 362         }
 363 
 364         // get current archive name
 365         jsa = new File(TestCommon.getCurrentArchiveName());
 366         if (!jsa.exists()) {
 367             throw new IOException(jsa + " does not exist!");
 368         }
 369 
 370         setReadWritePermission(jsa);
 371 
 372         // save as original untouched
 373         orgJsaFile = new File(new File(currentDir), "appcds.jsa.bak");
 374         copyFile(jsa, orgJsaFile);
 375 
 376 
 377         // modify jsa header, test should fail
 378         System.out.println("\n2. Corrupt header, should fail\n");
 379         modifyJsaHeader();



























 380         output = TestCommon.execCommon(execArgs);
 381         output.shouldContain("The shared archive file has the wrong version");
 382         output.shouldNotContain("Checksum verification failed");
 383 
 384         File newJsaFile = null;
 385         // modify content
 386         System.out.println("\n3. Corrupt Content, should fail\n");
 387         for (int i=0; i<num_regions; i++) {
 388             newJsaFile = new File(TestCommon.getNewArchiveName(shared_region_name[i]));
 389             copyFile(orgJsaFile, newJsaFile);
 390             if (modifyJsaContent(i)) {
 391                 testAndCheck(execArgs);

 392             }
 393         }
 394 
 395         // modify both header and content, test should fail
 396         System.out.println("\n4. Corrupt Header and Content, should fail\n");
 397         newJsaFile = new File(TestCommon.getNewArchiveName("header-and-content"));
 398         copyFile(orgJsaFile, newJsaFile);
 399         modifyJsaHeader();
 400         modifyJsaContent(0);  // this will not be reached since failed on header change first

 401         output = TestCommon.execCommon(execArgs);
 402         output.shouldContain("The shared archive file has the wrong version");
 403         output.shouldNotContain("Checksum verification failed");
 404 
 405         // delete bytes in data section
 406         System.out.println("\n5. Delete bytes at beginning of data section, should fail\n");
 407         copyFile(orgJsaFile, jsa, true);

 408         testAndCheck(verifyExecArgs);
 409 
 410         // insert bytes in data section forward
 411         System.out.println("\n6. Insert bytes at beginning of data section, should fail\n");
 412         copyFile(orgJsaFile, jsa, false);
 413         testAndCheck(verifyExecArgs);
 414 
 415         System.out.println("\n7. modify Content in random areas, should fail\n");
 416         newJsaFile = new File(TestCommon.getNewArchiveName("random-areas"));
 417         copyFile(orgJsaFile, newJsaFile);
 418         modifyJsaContentRandomly();

 419         testAndCheck(verifyExecArgs);
 420     }
 421 }


  44 import java.io.FileOutputStream;
  45 import java.io.IOException;
  46 import java.nio.ByteBuffer;
  47 import java.nio.ByteOrder;
  48 import java.nio.channels.FileChannel;
  49 import java.nio.file.Files;
  50 import java.nio.file.Path;
  51 import java.nio.file.Paths;
  52 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
  53 import java.nio.file.StandardOpenOption;
  54 import static java.nio.file.StandardOpenOption.READ;
  55 import static java.nio.file.StandardOpenOption.WRITE;
  56 import java.util.ArrayList;
  57 import java.util.HashSet;
  58 import java.util.List;
  59 import java.util.Random;
  60 import sun.hotspot.WhiteBox;
  61 
  62 public class SharedArchiveConsistency {
  63     public static WhiteBox wb;
  64     public static int offset_magic;     // CDSFileMapHeaderBase::_magic
  65     public static int offset_version;   // CDSFileMapHeaderBase::_version
  66     public static int offset_jvm_ident; // FileMapHeader::_jvm_ident
  67     public static int sp_offset_crc;    // CDSFileMapRegion::_crc
  68     public static int offset_paths_misc_info_size;
  69     public static int file_header_size = -1;// total size of header, variant, need calculation
  70     public static int CDSFileMapRegion_size; // size of CDSFileMapRegion
  71     public static int sp_offset;       // offset of CDSFileMapRegion
  72     public static int sp_used_offset;  // offset of CDSFileMapRegion::_used
  73     public static int size_t_size;     // size of size_t
  74     public static int int_size;        // size of int
  75 
  76     public static File jsa;        // will be updated during test
  77     public static File orgJsaFile; // kept the original file not touched.
  78     // The following should be consistent with the enum in the C++ MetaspaceShared class
  79     public static String[] shared_region_name = {
  80         "mc",          // MiscCode
  81         "rw",          // ReadWrite
  82         "ro",          // ReadOnly
  83         "md",          // MiscData
  84         "first_closed_archive",
  85         "last_closed_archive",
  86         "first_open_archive",
  87         "last_open_archive"
  88     };
  89 
  90     public static int num_regions = shared_region_name.length;
  91     public static String[] matchMessages = {
  92         "Unable to use shared archive",
  93         "An error has occurred while processing the shared archive file.",
  94         "Checksum verification failed.",
  95         "The shared archive file has been truncated."
  96     };
  97 
  98     public static void getFileOffsetInfo() throws Exception {
  99         wb = WhiteBox.getWhiteBox();
 100         offset_magic = wb.getOffsetForName("FileMapHeader::_magic");
 101         offset_version = wb.getOffsetForName("FileMapHeader::_version");
 102         offset_jvm_ident = wb.getOffsetForName("FileMapHeader::_jvm_ident");
 103         sp_offset_crc = wb.getOffsetForName("CDSFileMapRegion::_crc");
 104         try {
 105             int nonExistOffset = wb.getOffsetForName("FileMapHeader::_non_exist_offset");
 106             System.exit(-1); // should fail
 107         } catch (Exception e) {
 108             // success
 109         }
 110 
 111         sp_offset = wb.getOffsetForName("FileMapHeader::_space[0]") - offset_magic;
 112         sp_used_offset = wb.getOffsetForName("CDSFileMapRegion::_used") - sp_offset_crc;
 113         size_t_size = wb.getOffsetForName("size_t_size");
 114         CDSFileMapRegion_size  = wb.getOffsetForName("CDSFileMapRegion_size");
 115     }
 116 
 117     public static int getFileHeaderSize(FileChannel fc) throws Exception {
 118         if (file_header_size != -1) {
 119             return file_header_size;
 120         }
 121         // this is not real header size, it is struct size
 122         int_size = wb.getOffsetForName("int_size");
 123         file_header_size = wb.getOffsetForName("file_header_size");
 124         offset_paths_misc_info_size = wb.getOffsetForName("FileMapHeader::_paths_misc_info_size") -
 125             offset_magic;
 126         int path_misc_info_size   = (int)readInt(fc, offset_paths_misc_info_size, int_size);
 127         file_header_size += path_misc_info_size;
 128         System.out.println("offset_paths_misc_info_size = " + offset_paths_misc_info_size);
 129         System.out.println("path_misc_info_size   = " + path_misc_info_size);
 130         System.out.println("file_header_size      = " + file_header_size);
 131         file_header_size = (int)align_up_page(file_header_size);
 132         System.out.println("file_header_size (aligned to page) = " + file_header_size);
 133         return file_header_size;
 134     }
 135 
 136     public static long align_up_page(long l) throws Exception {
 137         // wb is obtained in getFileOffsetInfo() which is called first in main() else we should call
 138         // WhiteBox.getWhiteBox() here first.
 139         int pageSize = wb.getVMPageSize();
 140         return (l + pageSize -1) & (~ (pageSize - 1));
 141     }
 142 
 143     private static long getRandomBetween(long start, long end) throws Exception {
 144         if (start > end) {
 145             throw new IllegalArgumentException("start must be less than end");
 146         }
 147         Random aRandom = Utils.getRandomInstance();
 148         int d = aRandom.nextInt((int)(end - start));
 149         if (d < 1) {
 150             d = 1;
 151         }
 152         return start + d;
 153     }
 154 
 155     public static long readInt(FileChannel fc, long offset, int nbytes) throws Exception {
 156         ByteBuffer bb = ByteBuffer.allocate(nbytes);
 157         bb.order(ByteOrder.nativeOrder());
 158         fc.position(offset);
 159         fc.read(bb);
 160         return  (nbytes > 4 ? bb.getLong(0) : bb.getInt(0));
 161     }
 162 
 163     public static void writeData(FileChannel fc, long offset, ByteBuffer bb) throws Exception {
 164         fc.position(offset);
 165         fc.write(bb);
 166         fc.force(true);
 167     }
 168 
 169     public static FileChannel getFileChannel(File jsaFile) throws Exception {
 170         List<StandardOpenOption> arry = new ArrayList<StandardOpenOption>();
 171         arry.add(READ);
 172         arry.add(WRITE);
 173         return FileChannel.open(jsaFile.toPath(), new HashSet<StandardOpenOption>(arry));
 174     }
 175 
 176     public static void modifyJsaContentRandomly(File jsaFile) throws Exception {
 177         FileChannel fc = getFileChannel(jsaFile);
 178         // corrupt random area in the data areas
 179         long[] used    = new long[num_regions];       // record used bytes
 180         long start0, start, end, off;
 181         int used_offset, path_info_size;
 182 
 183         int bufSize;
 184         System.out.printf("%-24s%12s%12s%16s\n", "Space Name", "Used bytes", "Reg Start", "Random Offset");
 185         start0 = getFileHeaderSize(fc);
 186         for (int i = 0; i < num_regions; i++) {
 187             used[i] = get_region_used_size_aligned(fc, i);
 188             start = start0;
 189             for (int j = 0; j < i; j++) {
 190                 start += align_up_page(used[j]);
 191             }
 192             end = start + used[i];
 193             if (start == end) {
 194                 continue; // Ignore empty regions
 195             }
 196             off = getRandomBetween(start, end);
 197             System.out.printf("%-24s%12d%12d%16d\n", shared_region_name[i], used[i], start, off);


 199                 bufSize = (int)(end - off + 1);
 200             } else {
 201                 bufSize = 1024;
 202             }
 203             ByteBuffer bbuf = ByteBuffer.wrap(new byte[bufSize]);
 204             writeData(fc, off, bbuf);
 205         }
 206         if (fc.isOpen()) {
 207             fc.close();
 208         }
 209     }
 210 
 211     static long get_region_used_size_aligned(FileChannel fc, int region) throws Exception {
 212         long n = sp_offset + CDSFileMapRegion_size * region + sp_used_offset;
 213         long alignment = WhiteBox.getWhiteBox().metaspaceReserveAlignment();
 214         long used = readInt(fc, n, size_t_size);
 215         used = (used + alignment - 1) & ~(alignment - 1);
 216         return used;
 217     }
 218 
 219     public static boolean modifyJsaContent(int region, File jsaFile) throws Exception {
 220         FileChannel fc = getFileChannel(jsaFile);
 221         byte[] buf = new byte[4096];
 222         ByteBuffer bbuf = ByteBuffer.wrap(buf);
 223 
 224         long total = 0L;
 225         long[] used = new long[num_regions];
 226         System.out.printf("%-24s%12s\n", "Space name", "Used bytes");
 227         for (int i = 0; i < num_regions; i++) {
 228             used[i] = get_region_used_size_aligned(fc, i);
 229             System.out.printf("%-24s%12d\n", shared_region_name[i], used[i]);
 230             total += used[i];
 231         }
 232         System.out.printf("%-24s%12d\n", "Total: ", total);
 233         long header_size = getFileHeaderSize(fc);
 234         long region_start_offset = header_size;
 235         for (int i=0; i<region; i++) {
 236             region_start_offset += used[i];
 237         }
 238         if (used[region] == 0) {
 239             System.out.println("Region " + shared_region_name[region] + " is empty. Nothing to corrupt.");
 240             return false;
 241         }
 242         System.out.println("Corrupt " + shared_region_name[region] + " section, start = " + region_start_offset
 243                            + " (header_size + 0x" + Long.toHexString(region_start_offset-header_size) + ")");
 244         long bytes_written = 0L;
 245         while (bytes_written < used[region]) {
 246             writeData(fc, region_start_offset + bytes_written, bbuf);
 247             bbuf.clear();
 248             bytes_written += 4096;
 249         }
 250         fc.force(true);
 251         if (fc.isOpen()) {
 252             fc.close();
 253         }
 254         return true;
 255     }
 256 
 257     public static void modifyJsaHeader(File jsaFile) throws Exception {
 258         FileChannel fc = getFileChannel(jsaFile);
 259         // screw up header info
 260         byte[] buf = new byte[getFileHeaderSize(fc)];
 261         ByteBuffer bbuf = ByteBuffer.wrap(buf);
 262         writeData(fc, 0L, bbuf);
 263         if (fc.isOpen()) {
 264             fc.close();
 265         }
 266     }
 267 
 268     public static void modifyJvmIdent() throws Exception {
 269         FileChannel fc = getFileChannel(jsa);
 270         int headerSize = getFileHeaderSize(fc);
 271         System.out.println("    offset_jvm_ident " + offset_jvm_ident);
 272         byte[] buf = new byte[256];
 273         ByteBuffer bbuf = ByteBuffer.wrap(buf);
 274         writeData(fc, (long)offset_jvm_ident, bbuf);
 275         if (fc.isOpen()) {
 276             fc.close();
 277         }
 278     }
 279 
 280     public static void modifyHeaderIntField(long offset, int value) throws Exception {
 281         FileChannel fc = getFileChannel(jsa);
 282         int headerSize = getFileHeaderSize(fc);
 283         System.out.println("    offset " + offset);
 284         byte[] buf = ByteBuffer.allocate(4).putInt(value).array();
 285         ByteBuffer bbuf = ByteBuffer.wrap(buf);
 286         writeData(fc, offset, bbuf);
 287         if (fc.isOpen()) {
 288             fc.close();
 289         }
 290     }
 291 
 292     public static void copyFile(File from, File to) throws Exception {
 293         if (to.exists()) {
 294             if(!to.delete()) {
 295                 throw new IOException("Could not delete file " + to);
 296             }
 297         }
 298         to.createNewFile();
 299         setReadWritePermission(to);
 300         Files.copy(from.toPath(), to.toPath(), REPLACE_EXISTING);
 301     }
 302 
 303     // Copy file with bytes deleted or inserted
 304     // del -- true, deleted, false, inserted
 305     public static void copyFile(File from, File to, boolean del) throws Exception {
 306         try (
 307             FileChannel inputChannel = new FileInputStream(from).getChannel();
 308             FileChannel outputChannel = new FileOutputStream(to).getChannel()
 309         ) {
 310             long size = inputChannel.size();
 311             int init_size = getFileHeaderSize(inputChannel);


 361     //   3) keep header correct but modify content in each region specified by shared_region_name[]
 362     //   4) update both header and content, test
 363     //   5) delete bytes in data begining
 364     //   6) insert bytes in data begining
 365     //   7) randomly corrupt data in each region specified by shared_region_name[]
 366     public static void main(String... args) throws Exception {
 367         // must call to get offset info first!!!
 368         getFileOffsetInfo();
 369         Path currentRelativePath = Paths.get("");
 370         String currentDir = currentRelativePath.toAbsolutePath().toString();
 371         System.out.println("Current relative path is: " + currentDir);
 372         // get jar file
 373         String jarFile = JarBuilder.getOrCreateHelloJar();
 374 
 375         // dump (appcds.jsa created)
 376         TestCommon.testDump(jarFile, null);
 377 
 378         // test, should pass
 379         System.out.println("1. Normal, should pass but may fail\n");
 380 
 381         String[] execArgs = {"-Xlog:cds", "-cp", jarFile, "Hello"};
 382         // tests that corrupt contents of the archive need to run with
 383         // VerifySharedSpaces enabled to detect inconsistencies
 384         String[] verifyExecArgs = {"-Xlog:cds", "-XX:+VerifySharedSpaces", "-cp", jarFile, "Hello"};
 385 
 386         OutputAnalyzer output = TestCommon.execCommon(execArgs);
 387 
 388         try {
 389             TestCommon.checkExecReturn(output, 0, true, "Hello World");
 390         } catch (Exception e) {
 391             TestCommon.checkExecReturn(output, 1, true, matchMessages[0]);
 392         }
 393 
 394         // get current archive name
 395         jsa = new File(TestCommon.getCurrentArchiveName());
 396         if (!jsa.exists()) {
 397             throw new IOException(jsa + " does not exist!");
 398         }
 399 
 400         setReadWritePermission(jsa);
 401 
 402         // save as original untouched
 403         orgJsaFile = new File(new File(currentDir), "appcds.jsa.bak");
 404         copyFile(jsa, orgJsaFile);
 405 

 406         // modify jsa header, test should fail
 407         System.out.println("\n2. Corrupt header, should fail\n");
 408         modifyJsaHeader(jsa);
 409         output = TestCommon.execCommon(execArgs);
 410         output.shouldContain("The shared archive file has a bad magic number");
 411         output.shouldNotContain("Checksum verification failed");
 412 
 413         copyFile(orgJsaFile, jsa);
 414         // modify _jvm_ident and _paths_misc_info_size, test should fail
 415         System.out.println("\n2a. Corrupt _jvm_ident and _paths_misc_info_size, should fail\n");
 416         modifyJvmIdent();
 417         modifyHeaderIntField(offset_paths_misc_info_size, Integer.MAX_VALUE);
 418         output = TestCommon.execCommon(execArgs);
 419         output.shouldContain("The shared archive file was created by a different version or build of HotSpot");
 420         output.shouldNotContain("Checksum verification failed");
 421 
 422         copyFile(orgJsaFile, jsa);
 423         // modify _magic and _paths_misc_info_size, test should fail
 424         System.out.println("\n2b. Corrupt _magic and _paths_misc_info_size, should fail\n");
 425         modifyHeaderIntField(offset_magic, 0x00000000);
 426         modifyHeaderIntField(offset_paths_misc_info_size, Integer.MAX_VALUE);
 427         output = TestCommon.execCommon(execArgs);
 428         output.shouldContain("The shared archive file has a bad magic number");
 429         output.shouldNotContain("Checksum verification failed");
 430 
 431         copyFile(orgJsaFile, jsa);
 432         // modify _version and _paths_misc_info_size, test should fail
 433         System.out.println("\n2c. Corrupt _version and _paths_misc_info_size, should fail\n");
 434         modifyHeaderIntField(offset_version, 0x00000000);
 435         modifyHeaderIntField(offset_paths_misc_info_size, Integer.MAX_VALUE);
 436         output = TestCommon.execCommon(execArgs);
 437         output.shouldContain("The shared archive file has the wrong version");
 438         output.shouldNotContain("Checksum verification failed");
 439 
 440         File newJsaFile = null;
 441         // modify content
 442         System.out.println("\n3. Corrupt Content, should fail\n");
 443         for (int i=0; i<num_regions; i++) {
 444             newJsaFile = new File(TestCommon.getNewArchiveName(shared_region_name[i]));
 445             copyFile(orgJsaFile, newJsaFile);
 446             TestCommon.setCurrentArchiveName(newJsaFile.toString());
 447             if (modifyJsaContent(i, newJsaFile)) {
 448                 testAndCheck(verifyExecArgs);
 449             }
 450         }
 451 
 452         // modify both header and content, test should fail
 453         System.out.println("\n4. Corrupt Header and Content, should fail\n");
 454         newJsaFile = new File(TestCommon.getNewArchiveName("header-and-content"));
 455         copyFile(orgJsaFile, newJsaFile);
 456         TestCommon.setCurrentArchiveName(newJsaFile.toString());
 457         modifyJsaHeader(newJsaFile);
 458         modifyJsaContent(0, newJsaFile);  // this will not be reached since failed on header change first
 459         output = TestCommon.execCommon(execArgs);
 460         output.shouldContain("The shared archive file has a bad magic number");
 461         output.shouldNotContain("Checksum verification failed");
 462 
 463         // delete bytes in data section
 464         System.out.println("\n5. Delete bytes at beginning of data section, should fail\n");
 465         copyFile(orgJsaFile, jsa, true);
 466         TestCommon.setCurrentArchiveName(jsa.toString());
 467         testAndCheck(verifyExecArgs);
 468 
 469         // insert bytes in data section forward
 470         System.out.println("\n6. Insert bytes at beginning of data section, should fail\n");
 471         copyFile(orgJsaFile, jsa, false);
 472         testAndCheck(verifyExecArgs);
 473 
 474         System.out.println("\n7. modify Content in random areas, should fail\n");
 475         newJsaFile = new File(TestCommon.getNewArchiveName("random-areas"));
 476         copyFile(orgJsaFile, newJsaFile);
 477         TestCommon.setCurrentArchiveName(newJsaFile.toString());
 478         modifyJsaContentRandomly(newJsaFile);
 479         testAndCheck(verifyExecArgs);
 480     }
 481 }
< prev index next >