/* * Copyright (c) 2021, 2022, 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.
*/ package jdk.test.lib.cds;
// This class performs operations on shared archive file publicclass CDSArchiveUtils { // Minimum supported CDS file header version privatestaticint genericHeaderMinVersion; // CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION privatestaticint currentCDSArchiveVersion; // CURRENT_CDS_ARCHIVE_VERSION // offsets privatestaticint offsetMagic; // offset of GenericCDSFileMapHeader::_magic privatestaticint offsetCrc; // offset of GenericCDSFileMapHeader::_crc privatestaticint offsetVersion; // offset of GenericCDSFileMapHeader::_version privatestaticint offsetHeaderSize; // offset of GenericCDSFileMapHeader::_header_size privatestaticint offsetCommonAppClasspathPrefixSize;// offset of GenericCDSFileMapHeader::_common_app_classpath_size privatestaticint offsetBaseArchiveNameOffset;// offset of GenericCDSFileMapHeader::_base_archive_name_offset privatestaticint offsetBaseArchiveNameSize; // offset of GenericCDSFileMapHeader::_base_archive_name_size privatestaticint offsetJvmIdent; // offset of FileMapHeader::_jvm_ident privatestaticint spOffsetCrc; // offset of CDSFileMapRegion::_crc privatestaticint spOffset; // offset of CDSFileMapRegion privatestaticint spUsedOffset; // offset of CDSFileMapRegion::_used // constants privatestaticint staticMagic; // static magic value defined in hotspot privatestaticint dynamicMagic; // dyamic magic value defined in hotspot privatestaticint sizetSize; // size of size_t privatestaticint intSize; // size of int privatestaticint staticArchiveHeaderSize; // static archive file header size privatestaticint dynamicArchiveHeaderSize; // dynamic archive file header size privatestaticint cdsFileMapRegionSize; // size of CDSFileMapRegion privatestaticlong alignment; // MetaspaceShared::core_region_alignment
// The following should be consistent with the enum in the C++ MetaspaceShared class privatestatic String[] shared_region_name = { "rw", // ReadWrite "ro", // ReadOnly "bm", // relocation bitmaps "first_closed_archive", "last_closed_archive", "first_open_archive", "last_open_archive"
}; privatestaticint num_regions = shared_region_name.length;
privatestaticvoid setReadWritePermission(File file) throws Exception { if (!file.canRead()) { if (!file.setReadable(true)) { thrownew IOException("Cannot modify file " + file + " as readable");
}
} if (!file.canWrite()) { if (!file.setWritable(true)) { thrownew IOException("Cannot modify file " + file + " as writable");
}
}
}
publicstaticlong getRandomBetween(long start, long end) throws Exception { if (start > end) { thrownew IllegalArgumentException("start must be less than end");
}
Random aRandom = Utils.getRandomInstance(); int d = aRandom.nextInt((int)(end - start)); if (d < 1) {
d = 1;
} return start + d;
}
publicstaticvoid modifyContentRandomly(File jsaFile) throws Exception { // corrupt random area in the data areas long[] used = newlong[num_regions]; // record used bytes long start0, start, end, offset; int bufSize;
publicstaticvoid modifyRegionContentRandomly(File jsaFile) throws Exception { // corrupt random area in the data areas long[] used = newlong[num_regions]; // record used bytes long start0, start, end, offset; int bufSize;
publicstaticboolean modifyRegionContent(int region, File jsaFile) throws Exception { long total = 0L; long[] used = newlong[num_regions];
System.out.printf("%-24s%12s\n", "Space name", "Used bytes"); for (int i = 0; i < num_regions; i++) {
used[i] = usedRegionSizeAligned(jsaFile, i);
System.out.printf("%-24s%12d\n", shared_region_name[i], used[i]);
total += used[i];
} if (used[region] == 0) {
System.out.println("Region " + shared_region_name[region] + " is empty. Nothing to corrupt."); returnfalse;
} byte[] buf = newbyte[4096];
System.out.printf("%-24s%12d\n", "Total: ", total); long regionStartOffset = fileHeaderSizeAligned(jsaFile); for (int i = 0; i < region; i++) {
regionStartOffset += used[i];
}
System.out.println("Corrupt " + shared_region_name[region] + " section, start = " + regionStartOffset
+ " (header_size + 0x" + Long.toHexString(regionStartOffset - fileHeaderSizeAligned(jsaFile)) + ")"); long bytesWritten = 0L; while (bytesWritten < used[region]) {
bytesWritten += writeData(jsaFile, regionStartOffset + bytesWritten, buf);
} returntrue;
}
publicstaticvoid modifyRegionCrc(File jsaFile, int region, int value) throws Exception { long regionCrcOffset = spOffset + region * spOffsetCrc;
writeData(jsaFile, regionCrcOffset, value);
}
publicstaticvoid modifyAllRegionsCrc(File jsaFile) throws Exception { int value = 0xbadebabe; long[] used = newlong[num_regions]; for (int i = 0; i < num_regions; i++) {
used[i] = usedRegionSizeAligned(jsaFile, i); if (used[i] == 0) { // skip empty region continue;
}
modifyRegionCrc(jsaFile, i, value);
}
}
publicstaticvoid modifyFileHeader(File jsaFile) throws Exception { // screw up header info byte[] buf = newbyte[(int)fileHeaderSize(jsaFile)];
writeData(jsaFile, 0, buf);
}
publicstaticlong writeData(File file, long offset, int value) throws Exception { try (FileChannel fc = getFileChannel(file, true/*write*/)) {
ByteBuffer bbuf = ByteBuffer.allocate(4)
.order(ByteOrder.nativeOrder())
.putInt(value)
.rewind(); return writeData(fc, offset, bbuf);
}
}
// Helper method for calling FileChannel.transferFrom and checking the // return value. privatestaticvoid transferFrom(FileChannel inputChannel,
FileChannel outputChannel, long offset, long length) throws Exception { long position = offset; long count = length; while (count > 0 && inputChannel.position() < inputChannel.size()) { long n = outputChannel.transferFrom(inputChannel, position, count); if (n < 0 || n > count) { thrownew RuntimeException("Incorrect transfer length n = " + n
+ " (expected 0 <= n <= " + length + ")");
}
position += n;
count -= n;
}
}
// dstFile will keep original size publicstatic File insertBytesRandomlyAfterHeader(File orgFile, String newFileName) throws Exception { long headerSize = fileHeaderSize(orgFile); long dupSize = getRandomBetween(0L, headerSize);
File dstFile = new File(newFileName); try (FileChannel inputChannel = new FileInputStream(orgFile).getChannel();
FileChannel outputChannel = new FileOutputStream(dstFile).getChannel()) { long orgSize = inputChannel.size(); // Copy the header
transferFrom(inputChannel, outputChannel, 0, headerSize); // Copy dupSize bytes from the end of the header. Then, copy the rest // of the input such that the new file will have the same size as // the old file.
inputChannel.position(headerSize - dupSize);
transferFrom(inputChannel, outputChannel, headerSize, orgSize - headerSize);
} return dstFile;
}
// delete nBytes bytes from offset, so new file will be smaller than the original publicstatic File deleteBytesAtRandomPositionAfterHeader(File orgFile, String newFileName, int nBytes) throws Exception { long offset = fileHeaderSize(orgFile) + getRandomBetween(0L, 4096L);
File dstFile = new File(newFileName); try (FileChannel inputChannel = new FileInputStream(orgFile).getChannel();
FileChannel outputChannel = new FileOutputStream(dstFile).getChannel()) { long orgSize = inputChannel.size();
transferFrom(inputChannel, outputChannel, 0, offset);
inputChannel.position(offset + nBytes);
transferFrom(inputChannel, outputChannel, offset, orgSize - nBytes);
} return dstFile;
}
// returns the size of the last region with used bytes > 0. privatestaticlong getLastUsedRegionSize(File jsaFile) throws Exception { int i = num_regions - 1; long regionSize = 0; while (i >= 0) {
regionSize = usedRegionSizeAligned(jsaFile, i); if (regionSize > 0) { break;
}
i--;
} return regionSize;
}
// delete last regions's used bytes at the end, so new file will be smaller than the original publicstatic File deleteBytesAtTheEnd(File orgFile, String newFileName) throws Exception { long offset = fileHeaderSize(orgFile); long bytesToDelete = getLastUsedRegionSize(orgFile);
File dstFile = new File(newFileName); try (FileChannel inputChannel = new FileInputStream(orgFile).getChannel();
FileChannel outputChannel = new FileOutputStream(dstFile).getChannel()) { long orgSize = inputChannel.size();
transferFrom(inputChannel, outputChannel, 0, offset);
inputChannel.position(offset);
transferFrom(inputChannel, outputChannel, offset, orgSize - bytesToDelete);
} return dstFile;
}
// used region size publicstaticlong usedRegionSizeAligned(File archiveFile, int region) throws Exception { long offset = spOffset + cdsFileMapRegionSize * region + spUsedOffset; long used = readInt(archiveFile, offset, sizetSize); return alignUpWithAlignment(used);
}
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.