< prev index next >
src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java
Print this page
rev 16767 : 8175561: Memory churn in jimage code affects startup after resource encapsulation changes
Reviewed-by: jlaskey
rev 16768 : imported patch imgstr_oneup
@@ -57,37 +57,29 @@
ImageStrings getStrings() {
return strings;
}
- private static int attributeLength(int data) {
- return (data & 0x7) + 1;
- }
-
- private static int attributeKind(int data) {
- return data >>> 3;
- }
-
static long[] decompress(ByteBuffer bytes) {
Objects.requireNonNull(bytes);
long[] attributes = new long[ATTRIBUTE_COUNT];
if (bytes != null) {
while (bytes.hasRemaining()) {
int data = bytes.get() & 0xFF;
- int kind = attributeKind(data);
+ int kind = data >>> 3;
if (kind == ATTRIBUTE_END) {
break;
}
if (kind < ATTRIBUTE_END || ATTRIBUTE_COUNT <= kind) {
throw new InternalError(
"Invalid jimage attribute kind: " + kind);
}
- int length = attributeLength(data);
+ int length = (data & 0x7) + 1;
long value = 0;
for (int j = 0; j < length; j++) {
value <<= 8;
@@ -126,13 +118,87 @@
return stream.toArray();
}
public boolean verify(String name) {
+ return verify(name, attributes, strings);
+ }
+
+ /**
+ * A simpler verification would be {@code name.equals(getFullName())}, but
+ * by not creating the full name and enabling early returns we allocate
+ * fewer objects. Could possibly be made allocation free by extending
+ * ImageStrings to test if strings at an offset match the name region.
+ */
+ static boolean verify(String name, final long[] attributes,
+ final ImageStrings strings) {
Objects.requireNonNull(name);
+ final int length = name.length();
+ int index = 0;
+ int moduleOffset = (int)attributes[ATTRIBUTE_MODULE];
+ if (moduleOffset != 0) {
+ String module = strings.get(moduleOffset);
+ final int moduleLen = module.length();
+ index = moduleLen + 1;
+ if (length <= index
+ || name.charAt(0) != '/'
+ || !name.regionMatches(1, module, 0, moduleLen)
+ || name.charAt(index++) != '/') {
+ return false;
+ }
+ }
- return name.equals(getFullName());
+ return verifyName(name, index, length, attributes, strings);
+ }
+
+ static boolean verify(String module, String name,
+ final long[] attributes, final ImageStrings strings) {
+ Objects.requireNonNull(module);
+ Objects.requireNonNull(name);
+ int moduleOffset = (int)attributes[ATTRIBUTE_MODULE];
+ if (moduleOffset != 0) {
+ if (!module.equals(strings.get(moduleOffset))) {
+ return false;
+ }
+ }
+
+ return verifyName(name, 0, name.length(), attributes, strings);
+ }
+
+ private static boolean verifyName(String name, int index, final int length,
+ final long[] attributes, final ImageStrings strings) {
+
+ int parentOffset = (int) attributes[ATTRIBUTE_PARENT];
+ if (parentOffset != 0) {
+ String parent = strings.get(parentOffset);
+ final int parentLen = parent.length();
+ if (!name.regionMatches(index, parent, 0, parentLen)) {
+ return false;
+ }
+ index += parentLen;
+ if (length <= index || name.charAt(index++) != '/') {
+ return false;
+ }
+ }
+ String base = strings.get((int) attributes[ATTRIBUTE_BASE]);
+ final int baseLen = base.length();
+ if (!name.regionMatches(index, base, 0, baseLen)) {
+ return false;
+ }
+ index += baseLen;
+ int extOffset = (int) attributes[ATTRIBUTE_EXTENSION];
+ if (extOffset != 0) {
+ String extension = strings.get(extOffset);
+ int extLen = extension.length();
+ if (length <= index
+ || name.charAt(index++) != '.'
+ || !name.regionMatches(index, extension, 0, extLen)) {
+ return false;
+ }
+ index += extLen;
+ }
+ return length == index;
}
long getAttribute(int kind) {
if (kind < ATTRIBUTE_END || ATTRIBUTE_COUNT <= kind) {
throw new InternalError(
< prev index next >