< prev index next >
src/java.base/share/classes/jdk/internal/jimage/BasicImageWriter.java
Print this page
@@ -23,228 +23,141 @@
* questions.
*/
package jdk.internal.jimage;
-import java.io.PrintStream;
import java.nio.ByteOrder;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
public final class BasicImageWriter {
+
+ public static final String IMAGE_EXT = ".jimage";
+ public static final String BOOT_NAME = "bootmodules";
+ public static final String BOOT_IMAGE_NAME = BOOT_NAME + IMAGE_EXT;
+
private final static int RETRY_LIMIT = 1000;
private ByteOrder byteOrder;
- private ImageStrings strings;
- private int count;
+ private ImageStringsWriter strings;
+ private int length;
private int[] redirect;
- private ImageLocation[] locations;
- private List<ImageLocation> input;
+ private ImageLocationWriter[] locations;
+ private List<ImageLocationWriter> input;
private ImageStream headerStream;
private ImageStream redirectStream;
private ImageStream locationOffsetStream;
private ImageStream locationStream;
private ImageStream allIndexStream;
- static class ImageBucket implements Comparable<ImageBucket> {
- final List<ImageLocation> list;
-
- ImageBucket() {
- this.list = new ArrayList<>();
- }
-
- void add(ImageLocation location) {
- list.add(location);
- }
-
- int getSize() {
- return list.size();
- }
-
- List<ImageLocation> getList() {
- return list;
- }
-
- ImageLocation getFirst() {
- assert !list.isEmpty() : "bucket should never be empty";
- return list.get(0);
- }
-
- @Override
- public int hashCode() {
- return getFirst().hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- return this == obj;
- }
-
- @Override
- public int compareTo(ImageBucket o) {
- return o.getSize() - getSize();
- }
- }
-
public BasicImageWriter() {
this(ByteOrder.nativeOrder());
}
public BasicImageWriter(ByteOrder byteOrder) {
this.byteOrder = byteOrder;
this.input = new ArrayList<>();
- this.strings = new ImageStrings();
+ this.strings = new ImageStringsWriter();
this.headerStream = new ImageStream(byteOrder);
this.redirectStream = new ImageStream(byteOrder);
this.locationOffsetStream = new ImageStream(byteOrder);
this.locationStream = new ImageStream(byteOrder);
this.allIndexStream = new ImageStream(byteOrder);
}
+ public ByteOrder getByteOrder() {
+ return byteOrder;
+ }
+
public int addString(String string) {
return addString(new UTF8String(string));
}
public int addString(UTF8String string) {
return strings.add(string);
}
- public void addLocation(String fullname, long contentOffset, long compressedSize, long uncompressedSize) {
- ImageLocation location = ImageLocation.newLocation(new UTF8String(fullname), strings, contentOffset, compressedSize, uncompressedSize);
- input.add(location);
- count++;
+ public String getString(int offset) {
+ UTF8String utf8 = strings.get(offset);
+ return utf8 != null? utf8.toString() : null;
}
- private void generatePerfectHash() {
- redo:
- while(true) {
- redirect = new int[count];
- locations = new ImageLocation[count];
-
- ImageBucket[] sorted = createBuckets();
-
- int free = 0;
-
- for (ImageBucket bucket : sorted) {
- if (bucket.getSize() != 1) {
- if (!packCollidedEntries(bucket, count)) {
- count = (count + 1) | 1;
-
- continue redo;
- }
- } else {
- for ( ; free < count && locations[free] != null; free++) {}
- assert free < count : "no free slots";
- locations[free] = bucket.getFirst();
- redirect[bucket.hashCode() % count] = -1 - free;
- free++;
- }
- }
-
- break;
- }
+ public void addLocation(String fullname, long contentOffset,
+ long compressedSize, long uncompressedSize) {
+ ImageLocationWriter location =
+ ImageLocationWriter.newLocation(new UTF8String(fullname), strings,
+ contentOffset, compressedSize, uncompressedSize);
+ input.add(location);
+ length++;
}
- private ImageBucket[] createBuckets() {
- ImageBucket[] buckets = new ImageBucket[count];
-
- input.stream().forEach((location) -> {
- int index = location.hashCode() % count;
- ImageBucket bucket = buckets[index];
-
- if (bucket == null) {
- buckets[index] = bucket = new ImageBucket();
+ ImageLocationWriter[] getLocations() {
+ return locations;
}
- bucket.add(location);
- });
-
- ImageBucket[] sorted = Arrays.asList(buckets).stream()
- .filter((bucket) -> (bucket != null))
- .sorted()
- .toArray(ImageBucket[]::new);
-
- return sorted;
+ int getLocationsCount() {
+ return input.size();
}
- private boolean packCollidedEntries(ImageBucket bucket, int count) {
- List<Integer> undo = new ArrayList<>();
- int base = UTF8String.HASH_MULTIPLIER + 1;
-
- int retry = 0;
-
- redo:
- while (true) {
- for (ImageLocation location : bucket.getList()) {
- int index = location.hashCode(base) % count;
+ private void generatePerfectHash() {
+ PerfectHashBuilder<ImageLocationWriter> builder =
+ new PerfectHashBuilder<>(
+ new PerfectHashBuilder.Entry<ImageLocationWriter>().getClass(),
+ new PerfectHashBuilder.Bucket<ImageLocationWriter>().getClass());
- if (locations[index] != null) {
- undo.stream().forEach((i) -> {
- locations[i] = null;
+ input.forEach((location) -> {
+ builder.put(location.getFullName(), location);
});
- undo.clear();
- base++;
+ builder.generate();
- if (base == 0) {
- base = 1;
- }
+ length = builder.getCount();
+ redirect = builder.getRedirect();
+ PerfectHashBuilder.Entry<ImageLocationWriter>[] order = builder.getOrder();
+ locations = new ImageLocationWriter[length];
- if (++retry > RETRY_LIMIT) {
- return false;
+ for (int i = 0; i < length; i++) {
+ locations[i] = order[i].getValue();
}
-
- continue redo;
- }
-
- locations[index] = location;
- undo.add(index);
- }
-
- redirect[bucket.hashCode() % count] = base;
-
- break;
- }
-
- return true;
}
private void prepareStringBytes() {
strings.getStream().align(2);
}
private void prepareRedirectBytes() {
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < length; i++) {
redirectStream.putInt(redirect[i]);
}
}
private void prepareLocationBytes() {
// Reserve location offset zero for empty locations
- locationStream.put(ImageLocation.ATTRIBUTE_END << 3);
+ locationStream.put(ImageLocationWriter.ATTRIBUTE_END << 3);
- for (int i = 0; i < count; i++) {
- ImageLocation location = locations[i];
+ for (int i = 0; i < length; i++) {
+ ImageLocationWriter location = locations[i];
if (location != null) {
location.writeTo(locationStream);
}
}
locationStream.align(2);
}
private void prepareOffsetBytes() {
- for (int i = 0; i < count; i++) {
- ImageLocation location = locations[i];
- locationOffsetStream.putInt(location != null ? location.getLocationOffset() : 0);
+ for (int i = 0; i < length; i++) {
+ ImageLocationWriter location = locations[i];
+ int offset = location != null ? location.getLocationOffset() : 0;
+ locationOffsetStream.putInt(offset);
}
}
private void prepareHeaderBytes() {
- ImageHeader header = new ImageHeader(count, locationStream.getSize(), strings.getSize());
+ ImageHeader header = new ImageHeader(input.size(), length,
+ locationStream.getSize(), strings.getSize());
header.writeTo(headerStream);
}
private void prepareTableBytes() {
allIndexStream.put(headerStream);
@@ -266,35 +179,17 @@
}
return allIndexStream.toArray();
}
- ImageLocation find(UTF8String key) {
- int index = key.hashCode() % count;
- index = redirect[index];
+ ImageLocationWriter find(UTF8String key) {
+ int index = redirect[key.hashCode() % length];
if (index < 0) {
index = -index - 1;
- ImageLocation location = locations[index];
-
- return location;
} else {
- index = key.hashCode(index) % count;
- ImageLocation location = locations[index];
-
- return location;
- }
+ index = key.hashCode(index) % length;
}
- public void statistics() {
- getBytes();
- PrintStream out = System.out;
- out.println("Count: " + count);
- out.println("Header bytes size: " + headerStream.getSize());
- out.println("Redirect bytes size: " + redirectStream.getSize());
- out.println("Offset bytes size: " + locationOffsetStream.getSize());
- out.println("Location bytes size: " + locationStream.getSize());
- out.println("String count: " + strings.getCount());
- out.println("String bytes size: " + strings.getSize());
- out.println("Total bytes size: " + allIndexStream.getSize());
+ return locations[index];
}
}
< prev index next >